summaryrefslogtreecommitdiff
path: root/chromium/third_party/skia/tools
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-29 16:35:13 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-01 15:33:35 +0000
commitc8c2d1901aec01e934adf561a9fdf0cc776cdef8 (patch)
tree9157c3d9815e5870799e070b113813bec53e0535 /chromium/third_party/skia/tools
parentabefd5095b41dac94ca451d784ab6e27372e981a (diff)
downloadqtwebengine-chromium-c8c2d1901aec01e934adf561a9fdf0cc776cdef8.tar.gz
BASELINE: Update Chromium to 64.0.3282.139
Change-Id: I1cae68fe9c94ff7608b26b8382fc19862cdb293a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/third_party/skia/tools')
-rw-r--r--chromium/third_party/skia/tools/SkRandomScalerContext.cpp258
-rw-r--r--chromium/third_party/skia/tools/SkRandomScalerContext.h54
-rw-r--r--chromium/third_party/skia/tools/SkTestScalerContext.cpp267
-rw-r--r--chromium/third_party/skia/tools/SkTestScalerContext.h102
-rw-r--r--chromium/third_party/skia/tools/android/upload_to_android.py92
-rw-r--r--chromium/third_party/skia/tools/bookmaker/bookmaker.cpp987
-rw-r--r--chromium/third_party/skia/tools/bookmaker/bookmaker.h408
-rw-r--r--chromium/third_party/skia/tools/bookmaker/cataloger.cpp143
-rw-r--r--chromium/third_party/skia/tools/bookmaker/definition.cpp1274
-rw-r--r--chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp149
-rw-r--r--chromium/third_party/skia/tools/bookmaker/includeParser.cpp113
-rw-r--r--chromium/third_party/skia/tools/bookmaker/includeWriter.cpp298
-rw-r--r--chromium/third_party/skia/tools/bookmaker/mdOut.cpp74
-rw-r--r--chromium/third_party/skia/tools/bookmaker/parserCommon.cpp163
-rw-r--r--chromium/third_party/skia/tools/bookmaker/spellCheck.cpp14
-rw-r--r--chromium/third_party/skia/tools/calmbench/ab.py57
-rw-r--r--chromium/third_party/skia/tools/calmbench/calmbench.py52
-rw-r--r--chromium/third_party/skia/tools/colorspaceinfo.cpp6
-rw-r--r--chromium/third_party/skia/tools/create_flutter_test_images.cpp14
-rw-r--r--chromium/third_party/skia/tools/debugger/SkDebugCanvas.h19
-rw-r--r--chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp6
-rw-r--r--chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.h1
-rw-r--r--chromium/third_party/skia/tools/dump_record.cpp9
-rw-r--r--chromium/third_party/skia/tools/fiddle/draw.cpp25
-rw-r--r--chromium/third_party/skia/tools/fiddle/fiddle_main.cpp154
-rw-r--r--chromium/third_party/skia/tools/fiddle/fiddle_main.h31
-rw-r--r--chromium/third_party/skia/tools/fiddle/mesa_context.cpp31
-rw-r--r--chromium/third_party/skia/tools/flags/SkCommonFlags.cpp4
-rw-r--r--chromium/third_party/skia/tools/flags/SkCommonFlags.h3
-rw-r--r--chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp12
-rw-r--r--chromium/third_party/skia/tools/gdb/bitmap.py83
-rw-r--r--chromium/third_party/skia/tools/gpu/GrContextFactory.cpp31
-rw-r--r--chromium/third_party/skia/tools/gpu/GrContextFactory.h21
-rw-r--r--chromium/third_party/skia/tools/gpu/GrTest.cpp30
-rw-r--r--chromium/third_party/skia/tools/gpu/GrTest.h6
-rw-r--r--chromium/third_party/skia/tools/gpu/TestContext.cpp7
-rw-r--r--chromium/third_party/skia/tools/gpu/TestContext.h23
-rw-r--r--chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp455
-rw-r--r--chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h25
-rw-r--r--chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h37
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp24
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp120
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h2
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp4
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp41
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp31
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm15
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp19
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp156
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h17
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h16
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp1
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp16
-rw-r--r--chromium/third_party/skia/tools/gpu/mock/MockTestContext.cpp1
-rw-r--r--chromium/third_party/skia/tools/gpu/mtl/MtlTestContext.mm1
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkTestContext.cpp11
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp44
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkTestUtils.h23
-rw-r--r--chromium/third_party/skia/tools/gpucts/gm_knowledge.c12
-rw-r--r--chromium/third_party/skia/tools/gpucts/gm_knowledge.h57
-rw-r--r--chromium/third_party/skia/tools/gpucts/gm_runner.cpp109
-rw-r--r--chromium/third_party/skia/tools/gpucts/gm_runner.h65
-rw-r--r--chromium/third_party/skia/tools/gpucts/gpucts.cpp159
-rw-r--r--chromium/third_party/skia/tools/iOSShell.cpp90
-rw-r--r--chromium/third_party/skia/tools/iOSShell.h32
-rwxr-xr-xchromium/third_party/skia/tools/install_dependencies.sh1
-rwxr-xr-xchromium/third_party/skia/tools/mirror-dev.sh2
-rw-r--r--chromium/third_party/skia/tools/ok_test.cpp12
-rw-r--r--chromium/third_party/skia/tools/ok_vias.cpp36
-rw-r--r--chromium/third_party/skia/tools/rebaseline/toggle_legacy_flag.py159
-rw-r--r--chromium/third_party/skia/tools/sk_app/Application.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/Application.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/CommandSet.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/CommandSet.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/CommandSet.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/CommandSet.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/DisplayParams.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/DisplayParams.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/GLWindowContext.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/GLWindowContext.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/GLWindowContext.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/RasterWindowContext.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/RasterWindowContext.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.cpp)15
-rw-r--r--chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.h)9
-rw-r--r--chromium/third_party/skia/tools/sk_app/Window.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/Window.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/Window.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/Window.h)5
-rw-r--r--chromium/third_party/skia/tools/sk_app/WindowContext.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/WindowContext.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/GLWindowContext_android.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/RasterWindowContext_android.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/RasterWindowContext_android.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/VulkanWindowContext_android.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp)16
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/WindowContextFactory_android.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/WindowContextFactory_android.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/Window_android.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/Window_android.cpp)2
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/Window_android.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/Window_android.h)2
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/main_android.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/main_android.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/surface_glue_android.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.cpp)4
-rw-r--r--chromium/third_party/skia/tools/sk_app/android/surface_glue_android.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.h)2
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/ios/GLWindowContext_ios.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/ios/RasterWindowContext_ios.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/ios/WindowContextFactory_ios.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/ios/Window_ios.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/Window_ios.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/ios/Window_ios.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/ios/main_ios.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/ios/main_ios.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/mac/WindowContextFactory_mac.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/mac/Window_mac.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/Window_mac.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/mac/Window_mac.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/mac/main_mac.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/mac/main_mac.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/RasterWindowContext_unix.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/VulkanWindowContext_unix.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp)21
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/WindowContextFactory_unix.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/WindowContextFactory_unix.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/Window_unix.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/Window_unix.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/Window_unix.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/unix/main_unix.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/unix/main_unix.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/ANGLEWindowContext_win.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/GLWindowContext_win.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/RasterWindowContext_win.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/RasterWindowContext_win.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/VulkanWindowContext_win.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp)22
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/WindowContextFactory_win.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/Window_win.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/Window_win.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/Window_win.h (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/Window_win.h)0
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/main_win.cpp (renamed from chromium/third_party/skia/tools/viewer/sk_app/win/main_win.cpp)0
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils.cpp179
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils.h36
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils_flags.h16
-rw-r--r--chromium/third_party/skia/tools/sk_tool_utils_font.cpp2
-rw-r--r--chromium/third_party/skia/tools/skiaserve/Request.cpp8
-rw-r--r--chromium/third_party/skia/tools/skp/webpages_playback.py33
-rw-r--r--chromium/third_party/skia/tools/skp_parser.cpp18
-rw-r--r--chromium/third_party/skia/tools/skpbench/_adb.py12
-rw-r--r--chromium/third_party/skia/tools/skpbench/_adb_path.py4
-rw-r--r--chromium/third_party/skia/tools/skpbench/_hardware.py4
-rw-r--r--chromium/third_party/skia/tools/skpbench/_hardware_android.py25
-rw-r--r--chromium/third_party/skia/tools/skpbench/_hardware_nexus_6p.py63
-rw-r--r--chromium/third_party/skia/tools/skpbench/_hardware_pixel.py161
-rw-r--r--chromium/third_party/skia/tools/skpbench/_hardware_pixel_c.py48
-rw-r--r--chromium/third_party/skia/tools/skpbench/skpbench.cpp2
-rwxr-xr-xchromium/third_party/skia/tools/skpbench/skpbench.py112
-rw-r--r--chromium/third_party/skia/tools/valgrind.supp2
-rw-r--r--chromium/third_party/skia/tools/viewer/SampleSlide.cpp54
-rw-r--r--chromium/third_party/skia/tools/viewer/SampleSlide.h3
-rw-r--r--chromium/third_party/skia/tools/viewer/Slide.h4
-rw-r--r--chromium/third_party/skia/tools/viewer/Viewer.cpp426
-rw-r--r--chromium/third_party/skia/tools/viewer/Viewer.h17
140 files changed, 5905 insertions, 2236 deletions
diff --git a/chromium/third_party/skia/tools/SkRandomScalerContext.cpp b/chromium/third_party/skia/tools/SkRandomScalerContext.cpp
new file mode 100644
index 00000000000..49d9ab43ffd
--- /dev/null
+++ b/chromium/third_party/skia/tools/SkRandomScalerContext.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkGlyph.h"
+#include "SkMakeUnique.h"
+#include "SkPath.h"
+#include "SkRandomScalerContext.h"
+#include "SkRasterizer.h"
+
+class SkDescriptor;
+
+class SkRandomScalerContext : public SkScalerContext {
+public:
+ SkRandomScalerContext(sk_sp<SkRandomTypeface>, const SkScalerContextEffects&,
+ const SkDescriptor*, bool fFakeIt);
+
+protected:
+ unsigned generateGlyphCount() override;
+ uint16_t generateCharToGlyph(SkUnichar) override;
+ void generateAdvance(SkGlyph*) override;
+ void generateMetrics(SkGlyph*) override;
+ void generateImage(const SkGlyph&) override;
+ void generatePath(SkGlyphID, SkPath*) override;
+ void generateFontMetrics(SkPaint::FontMetrics*) override;
+
+private:
+ SkRandomTypeface* getRandomTypeface() const {
+ return static_cast<SkRandomTypeface*>(this->getTypeface());
+ }
+ std::unique_ptr<SkScalerContext> fProxy;
+ bool fFakeIt;
+};
+
+SkRandomScalerContext::SkRandomScalerContext(sk_sp<SkRandomTypeface> face,
+ const SkScalerContextEffects& effects,
+ const SkDescriptor* desc,
+ bool fakeIt)
+ : SkScalerContext(std::move(face), effects, desc)
+ , fFakeIt(fakeIt) {
+ fProxy = this->getRandomTypeface()->proxy()->createScalerContext(effects, desc);
+}
+
+unsigned SkRandomScalerContext::generateGlyphCount() {
+ return fProxy->getGlyphCount();
+}
+
+uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) {
+ return fProxy->charToGlyphID(uni);
+}
+
+void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) {
+ fProxy->getAdvance(glyph);
+}
+
+void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
+ // Here we will change the mask format of the glyph
+ // NOTE this is being overridden by the base class
+ SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers
+ switch (glyph->getGlyphID() % 4) {
+ case 0:
+ format = SkMask::kLCD16_Format;
+ break;
+ case 1:
+ format = SkMask::kA8_Format;
+ break;
+ case 2:
+ format = SkMask::kARGB32_Format;
+ break;
+ case 3:
+ format = SkMask::kBW_Format;
+ break;
+ }
+
+ fProxy->getMetrics(glyph);
+
+ glyph->fMaskFormat = format;
+ if (fFakeIt) {
+ return;
+ }
+ if (SkMask::kARGB32_Format == format) {
+ SkPath path;
+ fProxy->getPath(glyph->getPackedID(), &path);
+
+ SkRect storage;
+ const SkPaint& paint = this->getRandomTypeface()->paint();
+ const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
+ &storage,
+ SkPaint::kFill_Style);
+ SkIRect ibounds;
+ newBounds.roundOut(&ibounds);
+ glyph->fLeft = ibounds.fLeft;
+ glyph->fTop = ibounds.fTop;
+ glyph->fWidth = ibounds.width();
+ glyph->fHeight = ibounds.height();
+ } else {
+ SkPath devPath, fillPath;
+ SkMatrix fillToDevMatrix;
+
+ this->internalGetPath(glyph->getPackedID(), &fillPath, &devPath, &fillToDevMatrix);
+
+ // just use devPath
+ const SkIRect ir = devPath.getBounds().roundOut();
+
+ if (ir.isEmpty() || !ir.is16Bit()) {
+ glyph->fLeft = 0;
+ glyph->fTop = 0;
+ glyph->fWidth = 0;
+ glyph->fHeight = 0;
+ return;
+ }
+ glyph->fLeft = ir.fLeft;
+ glyph->fTop = ir.fTop;
+ glyph->fWidth = SkToU16(ir.width());
+ glyph->fHeight = SkToU16(ir.height());
+
+ if (glyph->fWidth > 0) {
+ switch (glyph->fMaskFormat) {
+ case SkMask::kLCD16_Format:
+ glyph->fWidth += 2;
+ glyph->fLeft -= 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
+ SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
+ switch (glyph.getGlyphID() % 4) {
+ case 0:
+ format = SkMask::kLCD16_Format;
+ break;
+ case 1:
+ format = SkMask::kA8_Format;
+ break;
+ case 2:
+ format = SkMask::kARGB32_Format;
+ break;
+ case 3:
+ format = SkMask::kBW_Format;
+ break;
+ }
+ const_cast<SkGlyph&>(glyph).fMaskFormat = format;
+
+ // if the format is ARGB, we just draw the glyph from path ourselves. Otherwise, we force
+ // our proxy context to generate the image from paths.
+ if (!fFakeIt) {
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+ SkPath path;
+ fProxy->getPath(glyph.getPackedID(), &path);
+
+ SkBitmap bm;
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage, glyph.rowBytes());
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ canvas.translate(-SkIntToScalar(glyph.fLeft),
+ -SkIntToScalar(glyph.fTop));
+ canvas.drawPath(path, this->getRandomTypeface()->paint());
+ } else {
+ fProxy->forceGenerateImageFromPath();
+ fProxy->getImage(glyph);
+ fProxy->forceOffGenerateImageFromPath();
+ }
+ } else {
+ sk_bzero(glyph.fImage, glyph.computeImageSize());
+ }
+}
+
+void SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
+ fProxy->generatePath(glyph, path);
+}
+
+void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
+ fProxy->getFontMetrics(metrics);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTypefaceCache.h"
+
+SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
+ : SkTypeface(proxy->fontStyle(), false)
+ , fProxy(std::move(proxy))
+ , fPaint(paint)
+ , fFakeIt(fakeIt) {}
+
+SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const {
+ return new SkRandomScalerContext(sk_ref_sp(const_cast<SkRandomTypeface*>(this)),
+ effects, desc, fFakeIt);
+}
+
+void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ fProxy->filterRec(rec);
+ rec->setHinting(SkPaint::kNo_Hinting);
+ rec->fMaskFormat = SkMask::kARGB32_Format;
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
+ return fProxy->getAdvancedMetrics();
+}
+
+SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const {
+ return fProxy->openStream(ttcIndex);
+}
+
+void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
+ bool* isLocal) const {
+ fProxy->getFontDescriptor(desc, isLocal);
+}
+
+int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const {
+ return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
+}
+
+int SkRandomTypeface::onCountGlyphs() const {
+ return fProxy->countGlyphs();
+}
+
+int SkRandomTypeface::onGetUPEM() const {
+ return fProxy->getUnitsPerEm();
+}
+
+void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
+ fProxy->getFamilyName(familyName);
+}
+
+SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
+ return fProxy->createFamilyNameIterator();
+}
+
+int SkRandomTypeface::onGetVariationDesignPosition(
+ SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
+{
+ return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
+}
+
+int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
+ return fProxy->getTableTags(tags);
+}
+
+size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
+ size_t length, void* data) const {
+ return fProxy->getTableData(tag, offset, length, data);
+}
+
diff --git a/chromium/third_party/skia/tools/SkRandomScalerContext.h b/chromium/third_party/skia/tools/SkRandomScalerContext.h
new file mode 100644
index 00000000000..b71689d9e2d
--- /dev/null
+++ b/chromium/third_party/skia/tools/SkRandomScalerContext.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRandomScalerContext_DEFINED
+#define SkRandomScalerContext_DEFINED
+
+#include "SkScalerContext.h"
+#include "SkTypeface.h"
+
+/*
+ * This scaler context is for debug only purposes. It will 'randomly' but deterministically return
+ * LCD / A8 / BW / RBGA masks based off of the Glyph ID
+ */
+
+class SkRandomTypeface : public SkTypeface {
+public:
+ SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint&, bool fakeit);
+
+ SkTypeface* proxy() const { return fProxy.get(); }
+ const SkPaint& paint() const { return fPaint; }
+
+protected:
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const override;
+ void onFilterRec(SkScalerContextRec*) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+ SkStreamAsset* onOpenStream(int* ttcIndex) const override;
+ void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override;
+
+ int onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const override;
+ int onCountGlyphs() const override;
+ int onGetUPEM() const override;
+
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override;
+ int onGetTableTags(SkFontTableTag tags[]) const override;
+ size_t onGetTableData(SkFontTableTag, size_t offset,
+ size_t length, void* data) const override;
+
+private:
+ sk_sp<SkTypeface> fProxy;
+ SkPaint fPaint;
+ bool fFakeIt;
+};
+
+#endif
diff --git a/chromium/third_party/skia/tools/SkTestScalerContext.cpp b/chromium/third_party/skia/tools/SkTestScalerContext.cpp
new file mode 100644
index 00000000000..f74b1bd57ac
--- /dev/null
+++ b/chromium/third_party/skia/tools/SkTestScalerContext.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkDescriptor.h"
+#include "SkFontDescriptor.h"
+#include "SkGlyph.h"
+#include "SkMakeUnique.h"
+#include "SkMask.h"
+#include "SkOTUtils.h"
+#include "SkPaintPriv.h"
+#include "SkScalerContext.h"
+#include "SkTestScalerContext.h"
+#include "SkTypefaceCache.h"
+#include "SkUtils.h"
+
+SkTestFont::SkTestFont(const SkTestFontData& fontData)
+ : INHERITED()
+ , fCharCodes(fontData.fCharCodes)
+ , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
+ , fWidths(fontData.fWidths)
+ , fMetrics(fontData.fMetrics)
+ , fName(fontData.fName)
+ , fPaths(nullptr)
+{
+ init(fontData.fPoints, fontData.fVerbs);
+}
+
+SkTestFont::~SkTestFont() {
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ delete fPaths[index];
+ }
+ delete[] fPaths;
+}
+
+int SkTestFont::codeToIndex(SkUnichar charCode) const {
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ if (fCharCodes[index] == (unsigned) charCode) {
+ return (int) index;
+ }
+ }
+ return 0;
+}
+
+void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
+ fPaths = new SkPath* [fCharCodesCount];
+ for (unsigned index = 0; index < fCharCodesCount; ++index) {
+ SkPath* path = new SkPath;
+ SkPath::Verb verb;
+ while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ path->moveTo(pts[0], pts[1]);
+ pts += 2;
+ break;
+ case SkPath::kLine_Verb:
+ path->lineTo(pts[0], pts[1]);
+ pts += 2;
+ break;
+ case SkPath::kQuad_Verb:
+ path->quadTo(pts[0], pts[1], pts[2], pts[3]);
+ pts += 4;
+ break;
+ case SkPath::kCubic_Verb:
+ path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
+ pts += 6;
+ break;
+ case SkPath::kClose_Verb:
+ path->close();
+ break;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return;
+ }
+ }
+ // This should make SkPath::getBounds() queries threadsafe.
+ path->updateBoundsCache();
+ fPaths[index] = path;
+ }
+}
+
+SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
+ : SkTypeface(style, false)
+ , fTestFont(std::move(testFont)) {
+}
+
+void SkTestTypeface::getAdvance(SkGlyph* glyph) {
+ // TODO(benjaminwagner): Update users to use floats.
+ glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
+ glyph->fAdvanceY = 0;
+}
+
+void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
+ *metrics = fTestFont->fMetrics;
+}
+
+void SkTestTypeface::getMetrics(SkGlyph* glyph) {
+ SkGlyphID glyphID = glyph->getGlyphID();
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+
+ // TODO(benjaminwagner): Update users to use floats.
+ glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
+ glyph->fAdvanceY = 0;
+}
+
+void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
+ glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
+ *path = *fTestFont->fPaths[glyphID];
+}
+
+void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
+ rec->setHinting(SkPaint::kNo_Hinting);
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
+ std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
+ info->fFontName.set(fTestFont->fName);
+ int glyphCount = this->onCountGlyphs();
+
+ SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode;
+ toUnicode.setCount(glyphCount);
+ SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount));
+ for (int gid = 0; gid < glyphCount; ++gid) {
+ toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]);
+ }
+ return info;
+}
+
+void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ desc->setFamilyName(fTestFont->fName);
+ desc->setStyle(this->fontStyle());
+ *isLocal = false;
+}
+
+int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const {
+ auto utf8 = (const char*)chars;
+ auto utf16 = (const uint16_t*)chars;
+ auto utf32 = (const SkUnichar*)chars;
+
+ for (int i = 0; i < glyphCount; i++) {
+ SkUnichar ch;
+ switch (encoding) {
+ case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8 ); break;
+ case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break;
+ case kUTF32_Encoding: ch = *utf32++; break;
+ }
+ if (glyphs) {
+ glyphs[i] = fTestFont->codeToIndex(ch);
+ }
+ }
+ return glyphCount;
+}
+
+void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
+ *familyName = fTestFont->fName;
+}
+
+SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
+ SkString familyName(fTestFont->fName);
+ SkString language("und"); //undetermined
+ return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+}
+
+class SkTestScalerContext : public SkScalerContext {
+public:
+ SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
+ const SkDescriptor* desc)
+ : SkScalerContext(std::move(face), effects, desc)
+ {
+ fRec.getSingleMatrix(&fMatrix);
+ this->forceGenerateImageFromPath();
+ }
+
+protected:
+ SkTestTypeface* getTestTypeface() const {
+ return static_cast<SkTestTypeface*>(this->getTypeface());
+ }
+
+ unsigned generateGlyphCount() override {
+ return this->getTestTypeface()->onCountGlyphs();
+ }
+
+ uint16_t generateCharToGlyph(SkUnichar uni) override {
+ uint16_t glyph;
+ (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
+ SkTypeface::kUTF32_Encoding, &glyph, 1);
+ return glyph;
+ }
+
+ void generateAdvance(SkGlyph* glyph) override {
+ this->getTestTypeface()->getAdvance(glyph);
+
+ const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
+ SkFloatToScalar(glyph->fAdvanceY));
+ glyph->fAdvanceX = SkScalarToFloat(advance.fX);
+ glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+ }
+
+ void generateMetrics(SkGlyph* glyph) override {
+ this->getTestTypeface()->getMetrics(glyph);
+
+ const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
+ SkFloatToScalar(glyph->fAdvanceY));
+ glyph->fAdvanceX = SkScalarToFloat(advance.fX);
+ glyph->fAdvanceY = SkScalarToFloat(advance.fY);
+
+ SkPath path;
+ this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
+ path.transform(fMatrix);
+
+ SkRect storage;
+ const SkPaint paint;
+ const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
+ &storage,
+ SkPaint::kFill_Style);
+ SkIRect ibounds;
+ newBounds.roundOut(&ibounds);
+ glyph->fLeft = ibounds.fLeft;
+ glyph->fTop = ibounds.fTop;
+ glyph->fWidth = ibounds.width();
+ glyph->fHeight = ibounds.height();
+ }
+
+ void generateImage(const SkGlyph& glyph) override {
+ SkPath path;
+ this->getTestTypeface()->getPath(glyph.getGlyphID(), &path);
+
+ SkBitmap bm;
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage, glyph.rowBytes());
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ canvas.translate(-SkIntToScalar(glyph.fLeft),
+ -SkIntToScalar(glyph.fTop));
+ canvas.concat(fMatrix);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ canvas.drawPath(path, paint);
+ }
+
+ void generatePath(SkGlyphID glyph, SkPath* path) override {
+ this->getTestTypeface()->getPath(glyph, path);
+ path->transform(fMatrix);
+ }
+
+ void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
+ this->getTestTypeface()->getFontMetrics(metrics);
+ SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
+ }
+
+private:
+ SkMatrix fMatrix;
+};
+
+SkScalerContext* SkTestTypeface::onCreateScalerContext(
+ const SkScalerContextEffects& effects, const SkDescriptor* desc) const
+{
+ return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
+}
diff --git a/chromium/third_party/skia/tools/SkTestScalerContext.h b/chromium/third_party/skia/tools/SkTestScalerContext.h
new file mode 100644
index 00000000000..e62210b2e30
--- /dev/null
+++ b/chromium/third_party/skia/tools/SkTestScalerContext.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTestScalerContext_DEFINED
+#define SkTestScalerContext_DEFINED
+
+#include "SkFixed.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkRefCnt.h"
+#include "SkTDArray.h"
+#include "SkTypeface.h"
+
+class SkTestFont;
+
+struct SkTestFontData {
+ const SkScalar* fPoints;
+ const unsigned char* fVerbs;
+ const unsigned* fCharCodes;
+ const size_t fCharCodesCount;
+ const SkFixed* fWidths;
+ const SkPaint::FontMetrics& fMetrics;
+ const char* fName;
+ SkFontStyle fStyle;
+ sk_sp<SkTestFont> fCachedFont;
+};
+
+class SkTestFont : public SkRefCnt {
+public:
+ SkTestFont(const SkTestFontData& );
+ virtual ~SkTestFont();
+ int codeToIndex(SkUnichar charCode) const;
+ void init(const SkScalar* pts, const unsigned char* verbs);
+private:
+ const unsigned* fCharCodes;
+ const size_t fCharCodesCount;
+ const SkFixed* fWidths;
+ const SkPaint::FontMetrics& fMetrics;
+ const char* fName;
+ SkPath** fPaths;
+ friend class SkTestTypeface;
+ typedef SkRefCnt INHERITED;
+};
+
+
+class SkTestTypeface : public SkTypeface {
+public:
+ SkTestTypeface(sk_sp<SkTestFont>, const SkFontStyle& style);
+ void getAdvance(SkGlyph* glyph);
+ void getFontMetrics(SkPaint::FontMetrics* metrics);
+ void getMetrics(SkGlyph* glyph);
+ void getPath(SkGlyphID glyph, SkPath* path);
+protected:
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor* desc) const override;
+ void onFilterRec(SkScalerContextRec* rec) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+
+ SkStreamAsset* onOpenStream(int* ttcIndex) const override {
+ return nullptr;
+ }
+
+ void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;
+
+ int onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const override;
+
+ int onCountGlyphs() const override {
+ return (int) fTestFont->fCharCodesCount;
+ }
+
+ int onGetUPEM() const override {
+ return 2048;
+ }
+
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override
+ {
+ return 0;
+ }
+
+ int onGetTableTags(SkFontTableTag tags[]) const override {
+ return 0;
+ }
+
+ size_t onGetTableData(SkFontTableTag tag, size_t offset,
+ size_t length, void* data) const override {
+ return 0;
+ }
+private:
+ sk_sp<SkTestFont> fTestFont;
+ friend class SkTestScalerContext;
+};
+
+#endif
diff --git a/chromium/third_party/skia/tools/android/upload_to_android.py b/chromium/third_party/skia/tools/android/upload_to_android.py
index 9afbf298d44..dba0c1692cc 100644
--- a/chromium/third_party/skia/tools/android/upload_to_android.py
+++ b/chromium/third_party/skia/tools/android/upload_to_android.py
@@ -52,7 +52,7 @@ def get_change_details(change_num):
return json.loads(content[5:])
-def upload_to_android(work_dir, change_num, debug):
+def init_work_dir(work_dir):
if not os.path.isdir(work_dir):
print 'Creating %s' % work_dir
os.makedirs(work_dir)
@@ -106,23 +106,34 @@ About to run repo init. If it hangs asking you to run glogin then please:
subprocess.check_call(
'git config user.email %s@google.com' % getpass.getuser(), shell=True)
- # Create repo branch.
- subprocess.check_call('%s start %s .' % (repo_binary, REPO_BRANCH_NAME),
- shell=True)
- try:
- change_details = get_change_details(change_num)
+ return repo_binary
+
+class Modifier:
+ def modify(self):
+ raise NotImplementedError
+ def get_user_msg(self):
+ raise NotImplementedError
+
+
+class FetchModifier(Modifier):
+ def __init__(self, change_num, debug):
+ self.change_num = change_num
+ self.debug = debug
+
+ def modify(self):
# Download and cherry-pick the patch.
+ change_details = get_change_details(self.change_num)
latest_patchset = len(change_details['revisions'])
- mod = int(change_num) % 100
+ mod = int(self.change_num) % 100
download_ref = 'refs/changes/%s/%s/%s' % (
- str(mod).zfill(2), change_num, latest_patchset)
+ str(mod).zfill(2), self.change_num, latest_patchset)
subprocess.check_call(
'git fetch https://skia.googlesource.com/skia %s' % download_ref,
shell=True)
subprocess.check_call('git cherry-pick FETCH_HEAD', shell=True)
- if debug:
+ if self.debug:
# Add SK_DEBUG to SkUserConfig.h.
with open(SK_USER_CONFIG_PATH, 'a') as f:
f.write('#ifndef SK_DEBUG\n')
@@ -140,17 +151,70 @@ About to run repo init. If it hangs asking you to run glogin then please:
'[DO ' + 'NOT ' + 'SUBMIT] %s\n\n'
'Test: Presubmit checks will test this change.' % (
original_commit_message))
+
subprocess.check_call('git commit --amend -m "%s"' % new_commit_message,
shell=True)
- # Upload to Android Gerrit.
- subprocess.check_call('%s upload --verify' % repo_binary, shell=True)
-
- print """
+ def get_user_msg(self):
+ return """
Open the above URL and trigger TH by checking 'Presubmit-Ready'.
You can download binaries (if required) from the TH link after it completes.
"""
+
+
+# Add a legacy flag if it doesn't exist, or remove it if it exists.
+class AndroidLegacyFlagModifier(Modifier):
+ def __init__(self, flag):
+ self.flag = flag
+ self.verb = "Unknown"
+
+ def modify(self):
+ flag_line = " #define %s\n" % self.flag
+
+ config_file = os.path.join('include', 'config', 'SkUserConfigManual.h')
+
+ with open(config_file) as f:
+ lines = f.readlines()
+
+ if flag_line not in lines:
+ lines.insert(
+ lines.index("#endif // SkUserConfigManual_DEFINED\n"), flag_line)
+ verb = "Add"
+ else:
+ lines.remove(flag_line)
+ verb = "Remove"
+
+ with open(config_file, 'w') as f:
+ for line in lines:
+ f.write(line)
+
+ subprocess.check_call('git add %s' % config_file, shell=True)
+ message = '%s %s\n\nTest: Presubmit checks will test this change.' % (
+ verb, self.flag)
+
+ subprocess.check_call('git commit -m "%s"' % message, shell=True)
+
+ def get_user_msg(self):
+ return """
+
+ Please open the above URL to review and land the change.
+"""
+
+
+def upload_to_android(work_dir, modifier):
+ repo_binary = init_work_dir(work_dir)
+
+ # Create repo branch.
+ subprocess.check_call('%s start %s .' % (repo_binary, REPO_BRANCH_NAME),
+ shell=True)
+ try:
+ modifier.modify()
+
+ # Upload to Android Gerrit.
+ subprocess.check_call('%s upload --verify' % repo_binary, shell=True)
+
+ print modifier.get_user_msg()
finally:
# Abandon repo branch.
subprocess.call('%s abandon %s' % (repo_binary, REPO_BRANCH_NAME),
@@ -171,7 +235,7 @@ def main():
'--debug', '-d', action='store_true', default=False,
help='Adds SK_DEBUG to SkUserConfig.h.')
args = parser.parse_args()
- upload_to_android(args.work_dir, args.change_num, args.debug)
+ upload_to_android(args.work_dir, FetchModifier(args.change_num, args.debug))
if __name__ == '__main__':
diff --git a/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp b/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp
index cc454982fd7..e0483758605 100644
--- a/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/bookmaker.cpp
@@ -7,19 +7,17 @@
#include "bookmaker.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-
DEFINE_string2(bmh, b, "", "Path to a *.bmh file or a directory.");
+DEFINE_bool2(catalog, c, false, "Write example catalog.htm. (Requires -b -f -r)");
DEFINE_string2(examples, e, "", "File of fiddlecli input, usually fiddle.json (For now, disables -r -f -s)");
DEFINE_string2(fiddle, f, "", "File of fiddlecli output, usually fiddleout.json.");
DEFINE_string2(include, i, "", "Path to a *.h file or a directory.");
DEFINE_bool2(hack, k, false, "Do a find/replace hack to update all *.bmh files. (Requires -b)");
DEFINE_bool2(stdout, o, false, "Write file out to standard out.");
DEFINE_bool2(populate, p, false, "Populate include from bmh. (Requires -b -i)");
-DEFINE_string2(ref, r, "", "Resolve refs and write bmh_*.md files to path. (Requires -b)");
+DEFINE_string2(ref, r, "", "Resolve refs and write bmh_*.md files to path. (Requires -b -f)");
DEFINE_string2(spellcheck, s, "", "Spell-check [once, all, mispelling]. (Requires -b)");
-DEFINE_string2(tokens, t, "", "Directory to write bmh from include. (Requires -i)");
+DEFINE_bool2(tokens, t, false, "Write bmh from include. (Requires -b -i)");
DEFINE_bool2(crosscheck, x, false, "Check bmh against includes. (Requires -b -i)");
DEFINE_bool2(skip, z, false, "Skip degenerate missed in legacy preprocessor.");
@@ -42,828 +40,6 @@ trouble with aliases, plurals
check for summary containing all methods
*/
-static string normalized_name(string name) {
- string normalizedName = name;
- std::replace(normalizedName.begin(), normalizedName.end(), '-', '_');
- do {
- size_t doubleColon = normalizedName.find("::", 0);
- if (string::npos == doubleColon) {
- break;
- }
- normalizedName = normalizedName.substr(0, doubleColon)
- + '_' + normalizedName.substr(doubleColon + 2);
- } while (true);
- return normalizedName;
-}
-
-static size_t count_indent(const string& text, size_t test, size_t end) {
- size_t result = test;
- while (test < end) {
- if (' ' != text[test]) {
- break;
- }
- ++test;
- }
- return test - result;
-}
-
-static void add_code(const string& text, int pos, int end,
- size_t outIndent, size_t textIndent, string& example) {
- do {
- // fix this to move whole paragraph in, out, but preserve doc indent
- int nextIndent = count_indent(text, pos, end);
- size_t len = text.find('\n', pos);
- if (string::npos == len) {
- len = end;
- }
- if ((size_t) (pos + nextIndent) < len) {
- size_t indent = outIndent + nextIndent;
- SkASSERT(indent >= textIndent);
- indent -= textIndent;
- for (size_t index = 0; index < indent; ++index) {
- example += ' ';
- }
- pos += nextIndent;
- while ((size_t) pos < len) {
- example += '"' == text[pos] ? "\\\"" :
- '\\' == text[pos] ? "\\\\" :
- text.substr(pos, 1);
- ++pos;
- }
- example += "\\n";
- } else {
- pos += nextIndent;
- }
- if ('\n' == text[pos]) {
- ++pos;
- }
- } while (pos < end);
-}
-
-// fixme: this will need to be more complicated to handle all of Skia
-// for now, just handle paint -- maybe fiddle will loosen naming restrictions
-void Definition::setCanonicalFiddle() {
- fMethodType = Definition::MethodType::kNone;
- size_t doubleColons = fName.find("::", 0);
- SkASSERT(string::npos != doubleColons);
- string base = fName.substr(0, doubleColons);
- string result = base + "_";
- doubleColons += 2;
- if (string::npos != fName.find('~', doubleColons)) {
- fMethodType = Definition::MethodType::kDestructor;
- result += "destructor";
- } else {
- bool isMove = string::npos != fName.find("&&", doubleColons);
- const char operatorStr[] = "operator";
- size_t opPos = fName.find(operatorStr, doubleColons);
- if (string::npos != opPos) {
- fMethodType = Definition::MethodType::kOperator;
- opPos += sizeof(operatorStr) - 1;
- if ('!' == fName[opPos]) {
- SkASSERT('=' == fName[opPos + 1]);
- result += "not_equal_operator";
- } else if ('=' == fName[opPos]) {
- if ('(' == fName[opPos + 1]) {
- result += isMove ? "move_" : "copy_";
- result += "assignment_operator";
- } else {
- SkASSERT('=' == fName[opPos + 1]);
- result += "equal_operator";
- }
- } else if ('[' == fName[opPos]) {
- result += "subscript_operator";
- const char* end = fContentStart;
- while (end > fStart && ' ' >= end[-1]) {
- --end;
- }
- string constCheck(fStart, end - fStart);
- size_t constPos = constCheck.rfind("const");
- if (constCheck.length() == constPos + 5) {
- result += "_const";
- }
- } else {
- SkASSERT(0); // todo: incomplete
- }
- } else {
- size_t parens = fName.find("()", doubleColons);
- if (string::npos != parens) {
- string methodName = fName.substr(doubleColons, parens - doubleColons);
- do {
- size_t nextDouble = methodName.find("::");
- if (string::npos == nextDouble) {
- break;
- }
- base = methodName.substr(0, nextDouble);
- result += base + '_';
- methodName = methodName.substr(nextDouble + 2);
- doubleColons += nextDouble + 2;
- } while (true);
- if (base == methodName) {
- fMethodType = Definition::MethodType::kConstructor;
- result += "empty_constructor";
- } else {
- result += fName.substr(doubleColons, fName.length() - doubleColons - 2);
- }
- } else {
- size_t openParen = fName.find('(', doubleColons);
- if (string::npos == openParen) {
- result += fName.substr(doubleColons);
- } else {
- size_t comma = fName.find(',', doubleColons);
- if (string::npos == comma) {
- result += isMove ? "move_" : "copy_";
- }
- fMethodType = Definition::MethodType::kConstructor;
- // name them by their param types,
- // e.g. SkCanvas__int_int_const_SkSurfaceProps_star
- // TODO: move forward until parens are balanced and terminator =,)
- TextParser params("", &fName[openParen] + 1, &*fName.end(), 0);
- bool underline = false;
- while (!params.eof()) {
- // SkDEBUGCODE(const char* end = params.anyOf("(),=")); // unused for now
- // SkASSERT(end[0] != '('); // fixme: put off handling nested parentheseses
- if (params.startsWith("const") || params.startsWith("int")
- || params.startsWith("Sk")) {
- const char* wordStart = params.fChar;
- params.skipToNonAlphaNum();
- if (underline) {
- result += '_';
- } else {
- underline = true;
- }
- result += string(wordStart, params.fChar - wordStart);
- } else {
- params.skipToNonAlphaNum();
- }
- if (!params.eof() && '*' == params.peek()) {
- if (underline) {
- result += '_';
- } else {
- underline = true;
- }
- result += "star";
- params.next();
- params.skipSpace();
- }
- params.skipToAlpha();
- }
- }
- }
- }
- }
- fFiddle = normalized_name(result);
-}
-
-bool Definition::exampleToScript(string* result) const {
- bool hasFiddle = true;
- const Definition* platform = this->hasChild(MarkType::kPlatform);
- if (platform) {
- TextParser platParse(platform);
- hasFiddle = !platParse.strnstr("!fiddle", platParse.fEnd);
- }
- if (!hasFiddle) {
- *result = "";
- return true;
- }
- string text = this->extractText(Definition::TrimExtract::kNo);
- const char drawWrapper[] = "void draw(SkCanvas* canvas) {";
- const char drawNoCanvas[] = "void draw(SkCanvas* ) {";
- size_t nonSpace = 0;
- while (nonSpace < text.length() && ' ' >= text[nonSpace]) {
- ++nonSpace;
- }
- bool hasFunc = !text.compare(nonSpace, sizeof(drawWrapper) - 1, drawWrapper);
- bool noCanvas = !text.compare(nonSpace, sizeof(drawNoCanvas) - 1, drawNoCanvas);
- bool hasCanvas = string::npos != text.find("SkCanvas canvas");
- SkASSERT(!hasFunc || !noCanvas);
- bool textOut = string::npos != text.find("SkDebugf(")
- || string::npos != text.find("dump(")
- || string::npos != text.find("dumpHex(");
- string heightStr = "256";
- string widthStr = "256";
- bool preprocessor = text[0] == '#';
- string normalizedName(fFiddle);
- string code;
- string imageStr = "0";
- for (auto const& iter : fChildren) {
- switch (iter->fMarkType) {
- case MarkType::kError:
- result->clear();
- return true;
- case MarkType::kHeight:
- heightStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
- break;
- case MarkType::kWidth:
- widthStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
- break;
- case MarkType::kDescription:
- // ignore for now
- break;
- case MarkType::kFunction: {
- // emit this, but don't wrap this in draw()
- string funcText(iter->fContentStart, iter->fContentEnd - iter->fContentStart - 1);
- size_t pos = 0;
- while (pos < funcText.length() && ' ' > funcText[pos]) {
- ++pos;
- }
- size_t indent = count_indent(funcText, pos, funcText.length());
- add_code(funcText, pos, funcText.length(), 0, indent, code);
- code += "\\n";
- } break;
- case MarkType::kComment:
- break;
- case MarkType::kImage:
- imageStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
- break;
- case MarkType::kToDo:
- break;
- case MarkType::kMarkChar:
- case MarkType::kPlatform:
- // ignore for now
- break;
- case MarkType::kStdOut:
- textOut = true;
- break;
- default:
- SkASSERT(0); // more coding to do
- }
- }
- string textOutStr = textOut ? "true" : "false";
- size_t pos = 0;
- while (pos < text.length() && ' ' > text[pos]) {
- ++pos;
- }
- size_t end = text.length();
- size_t outIndent = 0;
- size_t textIndent = count_indent(text, pos, end);
- bool wrapCode = !hasFunc && !noCanvas && !preprocessor;
- if (wrapCode) {
- code += hasCanvas ? drawNoCanvas : drawWrapper;
- code += "\\n";
- outIndent = 4;
- }
- add_code(text, pos, end, outIndent, textIndent, code);
- if (wrapCode) {
- code += "}";
- }
- string example = "\"" + normalizedName + "\": {\n";
- example += " \"code\": \"" + code + "\",\n";
- example += " \"options\": {\n";
- example += " \"width\": " + widthStr + ",\n";
- example += " \"height\": " + heightStr + ",\n";
- example += " \"source\": " + imageStr + ",\n";
- example += " \"srgb\": false,\n";
- example += " \"f16\": false,\n";
- example += " \"textOnly\": " + textOutStr + ",\n";
- example += " \"animated\": false,\n";
- example += " \"duration\": 0\n";
- example += " },\n";
- example += " \"fast\": true\n";
- example += "}";
- *result = example;
- return true;
-}
-
-static void space_pad(string* str) {
- size_t len = str->length();
- if (len == 0) {
- return;
- }
- char last = (*str)[len - 1];
- if ('~' == last || ' ' >= last) {
- return;
- }
- *str += ' ';
-}
-
-//start here;
-// see if it possible to abstract this a little bit so it can
-// additionally be used to find params and return in method prototype that
-// does not have corresponding doxygen comments
-bool Definition::checkMethod() const {
- SkASSERT(MarkType::kMethod == fMarkType);
- // if method returns a value, look for a return child
- // for each parameter, look for a corresponding child
- const char* end = fContentStart;
- while (end > fStart && ' ' >= end[-1]) {
- --end;
- }
- TextParser methodParser(fFileName, fStart, end, fLineCount);
- methodParser.skipWhiteSpace();
- SkASSERT(methodParser.startsWith("#Method"));
- methodParser.skipName("#Method");
- methodParser.skipSpace();
- string name = this->methodName();
- if (MethodType::kNone == fMethodType && name.length() > 2 &&
- "()" == name.substr(name.length() - 2)) {
- name = name.substr(0, name.length() - 2);
- }
- bool expectReturn = this->methodHasReturn(name, &methodParser);
- bool foundReturn = false;
- bool foundException = false;
- for (auto& child : fChildren) {
- foundException |= MarkType::kDeprecated == child->fMarkType
- || MarkType::kExperimental == child->fMarkType;
- if (MarkType::kReturn != child->fMarkType) {
- if (MarkType::kParam == child->fMarkType) {
- child->fVisited = false;
- }
- continue;
- }
- if (!expectReturn) {
- return methodParser.reportError<bool>("no #Return expected");
- }
- if (foundReturn) {
- return methodParser.reportError<bool>("multiple #Return markers");
- }
- foundReturn = true;
- }
- if (expectReturn && !foundReturn && !foundException) {
- return methodParser.reportError<bool>("missing #Return marker");
- }
- const char* paren = methodParser.strnchr('(', methodParser.fEnd);
- if (!paren) {
- return methodParser.reportError<bool>("missing #Method function definition");
- }
- const char* nextEnd = paren;
- do {
- string paramName;
- methodParser.fChar = nextEnd + 1;
- methodParser.skipSpace();
- if (!this->nextMethodParam(&methodParser, &nextEnd, &paramName)) {
- continue;
- }
- bool foundParam = false;
- for (auto& child : fChildren) {
- if (MarkType::kParam != child->fMarkType) {
- continue;
- }
- if (paramName != child->fName) {
- continue;
- }
- if (child->fVisited) {
- return methodParser.reportError<bool>("multiple #Method param with same name");
- }
- child->fVisited = true;
- if (foundParam) {
- TextParser paramError(child);
- return methodParser.reportError<bool>("multiple #Param with same name");
- }
- foundParam = true;
-
- }
- if (!foundParam && !foundException) {
- return methodParser.reportError<bool>("no #Param found");
- }
- if (')' == nextEnd[0]) {
- break;
- }
- } while (')' != nextEnd[0]);
- for (auto& child : fChildren) {
- if (MarkType::kParam != child->fMarkType) {
- continue;
- }
- if (!child->fVisited) {
- TextParser paramError(child);
- return paramError.reportError<bool>("#Param without param in #Method");
- }
- }
- return true;
-}
-
-bool Definition::crossCheck2(const Definition& includeToken) const {
- TextParser parser(fFileName, fStart, fContentStart, fLineCount);
- parser.skipExact("#");
- bool isMethod = parser.skipName("Method");
- const char* contentEnd;
- if (isMethod) {
- contentEnd = fContentStart;
- } else if (parser.skipName("DefinedBy")) {
- contentEnd = fContentEnd;
- while (parser.fChar < contentEnd && ' ' >= contentEnd[-1]) {
- --contentEnd;
- }
- if (parser.fChar < contentEnd - 1 && ')' == contentEnd[-1] && '(' == contentEnd[-2]) {
- contentEnd -= 2;
- }
- } else {
- return parser.reportError<bool>("unexpected crosscheck marktype");
- }
- return crossCheckInside(parser.fChar, contentEnd, includeToken);
-}
-
-bool Definition::crossCheck(const Definition& includeToken) const {
- return crossCheckInside(fContentStart, fContentEnd, includeToken);
-}
-
-bool Definition::crossCheckInside(const char* start, const char* end,
- const Definition& includeToken) const {
- TextParser def(fFileName, start, end, fLineCount);
- TextParser inc("", includeToken.fContentStart, includeToken.fContentEnd, 0);
- if (inc.startsWith("SK_API")) {
- inc.skipWord("SK_API");
- }
- if (inc.startsWith("friend")) {
- inc.skipWord("friend");
- }
- if (inc.startsWith("SK_API")) {
- inc.skipWord("SK_API");
- }
- do {
- bool defEof;
- bool incEof;
- do {
- defEof = def.eof() || !def.skipWhiteSpace();
- incEof = inc.eof() || !inc.skipWhiteSpace();
- if (!incEof && '/' == inc.peek() && (defEof || '/' != def.peek())) {
- inc.next();
- if ('*' == inc.peek()) {
- inc.skipToEndBracket("*/");
- inc.next();
- } else if ('/' == inc.peek()) {
- inc.skipToEndBracket('\n');
- }
- } else if (!incEof && '#' == inc.peek() && (defEof || '#' != def.peek())) {
- inc.next();
- if (inc.startsWith("if")) {
- inc.skipToEndBracket("\n");
- } else if (inc.startsWith("endif")) {
- inc.skipToEndBracket("\n");
- } else {
- SkASSERT(0); // incomplete
- return false;
- }
- } else {
- break;
- }
- inc.next();
- } while (true);
- if (defEof || incEof) {
- if (defEof == incEof || (!defEof && ';' == def.peek())) {
- return true;
- }
- return false; // allow setting breakpoint on failure
- }
- char defCh;
- do {
- defCh = def.next();
- char incCh = inc.next();
- if (' ' >= defCh && ' ' >= incCh) {
- break;
- }
- if (defCh != incCh) {
- return false;
- }
- if (';' == defCh) {
- return true;
- }
- } while (!def.eof() && !inc.eof());
- } while (true);
- return false;
-}
-
-string Definition::formatFunction() const {
- const char* end = fContentStart;
- while (end > fStart && ' ' >= end[-1]) {
- --end;
- }
- TextParser methodParser(fFileName, fStart, end, fLineCount);
- methodParser.skipWhiteSpace();
- SkASSERT(methodParser.startsWith("#Method"));
- methodParser.skipName("#Method");
- methodParser.skipSpace();
- const char* lastStart = methodParser.fChar;
- const int limit = 80; // todo: allow this to be set by caller or in global or something
- string methodStr;
- string name = this->methodName();
- const char* nameInParser = methodParser.strnstr(name.c_str(), methodParser.fEnd);
- methodParser.skipTo(nameInParser);
- const char* lastEnd = methodParser.fChar;
- const char* paren = methodParser.strnchr('(', methodParser.fEnd);
- size_t indent;
- if (paren) {
- indent = (size_t) (paren - lastStart) + 1;
- } else {
- indent = (size_t) (lastEnd - lastStart);
- }
- int written = 0;
- do {
- const char* nextStart = lastEnd;
- SkASSERT(written < limit);
- const char* delimiter = methodParser.anyOf(",)");
- const char* nextEnd = delimiter ? delimiter : methodParser.fEnd;
- if (delimiter) {
- while (nextStart < nextEnd && ' ' >= nextStart[0]) {
- ++nextStart;
- }
- }
- while (nextEnd > nextStart && ' ' >= nextEnd[-1]) {
- --nextEnd;
- }
- if (delimiter) {
- nextEnd += 1;
- delimiter += 1;
- }
- if (lastEnd > lastStart) {
- if (lastStart[0] != ' ') {
- space_pad(&methodStr);
- }
- methodStr += string(lastStart, (size_t) (lastEnd - lastStart));
- written += (size_t) (lastEnd - lastStart);
- }
- if (delimiter) {
- if (nextEnd - nextStart >= (ptrdiff_t) (limit - written)) {
- written = indent;
- methodStr += '\n';
- methodStr += string(indent, ' ');
- }
- methodParser.skipTo(delimiter);
- }
- lastStart = nextStart;
- lastEnd = nextEnd;
- } while (lastStart < lastEnd);
- return methodStr;
-}
-
-string Definition::fiddleName() const {
- string result;
- size_t start = 0;
- string parent;
- const Definition* parentDef = this;
- while ((parentDef = parentDef->fParent)) {
- if (MarkType::kClass == parentDef->fMarkType || MarkType::kStruct == parentDef->fMarkType) {
- parent = parentDef->fFiddle;
- break;
- }
- }
- if (parent.length() && 0 == fFiddle.compare(0, parent.length(), parent)) {
- start = parent.length();
- while (start < fFiddle.length() && '_' == fFiddle[start]) {
- ++start;
- }
- }
- size_t end = fFiddle.find_first_of('(', start);
- return fFiddle.substr(start, end - start);
-}
-
-const Definition* Definition::hasChild(MarkType markType) const {
- for (auto iter : fChildren) {
- if (markType == iter->fMarkType) {
- return iter;
- }
- }
- return nullptr;
-}
-
-const Definition* Definition::hasParam(const string& ref) const {
- SkASSERT(MarkType::kMethod == fMarkType);
- for (auto iter : fChildren) {
- if (MarkType::kParam != iter->fMarkType) {
- continue;
- }
- if (iter->fName == ref) {
- return &*iter;
- }
-
- }
- return nullptr;
-}
-
-bool Definition::methodHasReturn(const string& name, TextParser* methodParser) const {
- const char* lastStart = methodParser->fChar;
- const char* nameInParser = methodParser->strnstr(name.c_str(), methodParser->fEnd);
- methodParser->skipTo(nameInParser);
- const char* lastEnd = methodParser->fChar;
- const char* returnEnd = lastEnd;
- while (returnEnd > lastStart && ' ' == returnEnd[-1]) {
- --returnEnd;
- }
- bool expectReturn = 4 != returnEnd - lastStart || strncmp("void", lastStart, 4);
- if (MethodType::kNone != fMethodType && !expectReturn) {
- return methodParser->reportError<bool>("unexpected void");
- }
- switch (fMethodType) {
- case MethodType::kNone:
- case MethodType::kOperator:
- // either is fine
- break;
- case MethodType::kConstructor:
- expectReturn = true;
- break;
- case MethodType::kDestructor:
- expectReturn = false;
- break;
- }
- return expectReturn;
-}
-
-string Definition::methodName() const {
- string result;
- size_t start = 0;
- string parent;
- const Definition* parentDef = this;
- while ((parentDef = parentDef->fParent)) {
- if (MarkType::kClass == parentDef->fMarkType || MarkType::kStruct == parentDef->fMarkType) {
- parent = parentDef->fName;
- break;
- }
- }
- if (parent.length() && 0 == fName.compare(0, parent.length(), parent)) {
- start = parent.length();
- while (start < fName.length() && ':' == fName[start]) {
- ++start;
- }
- }
- if (fClone) {
- int lastUnder = fName.rfind('_');
- return fName.substr(start, (size_t) (lastUnder - start));
- }
- size_t end = fName.find_first_of('(', start);
- if (string::npos == end) {
- return fName.substr(start);
- }
- return fName.substr(start, end - start);
-}
-
-bool Definition::nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
- string* paramName) const {
- int parenCount = 0;
- TextParser::Save saveState(methodParser);
- while (true) {
- if (methodParser->eof()) {
- return methodParser->reportError<bool>("#Method function missing close paren");
- }
- char ch = methodParser->peek();
- if ('(' == ch) {
- ++parenCount;
- }
- if (parenCount == 0 && (')' == ch || ',' == ch)) {
- *nextEndPtr = methodParser->fChar;
- break;
- }
- if (')' == ch) {
- if (0 > --parenCount) {
- return this->reportError<bool>("mismatched parentheses");
- }
- }
- methodParser->next();
- }
- saveState.restore();
- const char* nextEnd = *nextEndPtr;
- const char* paramEnd = nextEnd;
- const char* assign = methodParser->strnstr(" = ", paramEnd);
- if (assign) {
- paramEnd = assign;
- }
- const char* closeBracket = methodParser->strnstr("]", paramEnd);
- if (closeBracket) {
- const char* openBracket = methodParser->strnstr("[", paramEnd);
- if (openBracket && openBracket < closeBracket) {
- while (openBracket < --closeBracket && isdigit(closeBracket[0]))
- ;
- if (openBracket == closeBracket) {
- paramEnd = openBracket;
- }
- }
- }
- const char* function = methodParser->strnstr(")(", paramEnd);
- if (function) {
- paramEnd = function;
- }
- while (paramEnd > methodParser->fChar && ' ' == paramEnd[-1]) {
- --paramEnd;
- }
- const char* paramStart = paramEnd;
- while (paramStart > methodParser->fChar && isalnum(paramStart[-1])) {
- --paramStart;
- }
- if (paramStart > methodParser->fChar && paramStart >= paramEnd) {
- return methodParser->reportError<bool>("#Method missing param name");
- }
- *paramName = string(paramStart, paramEnd - paramStart);
- if (!paramName->length()) {
- if (')' != nextEnd[0]) {
- return methodParser->reportError<bool>("#Method malformed param");
- }
- return false;
- }
- return true;
-}
-
- bool ParserCommon::parseFile(const char* fileOrPath, const char* suffix) {
- if (!sk_isdir(fileOrPath)) {
- if (!this->parseFromFile(fileOrPath)) {
- SkDebugf("failed to parse %s\n", fileOrPath);
- return false;
- }
- } else {
- SkOSFile::Iter it(fileOrPath, suffix);
- for (SkString file; it.next(&file); ) {
- SkString p = SkOSPath::Join(fileOrPath, file.c_str());
- const char* hunk = p.c_str();
- if (!SkStrEndsWith(hunk, suffix)) {
- continue;
- }
- if (!this->parseFromFile(hunk)) {
- SkDebugf("failed to parse %s\n", hunk);
- return false;
- }
- }
- }
- return true;
-}
-
-bool Definition::paramsMatch(const string& match, const string& name) const {
- TextParser def(fFileName, fStart, fContentStart, fLineCount);
- const char* dName = def.strnstr(name.c_str(), fContentStart);
- if (!dName) {
- return false;
- }
- def.skipTo(dName);
- TextParser m(fFileName, &match.front(), &match.back() + 1, fLineCount);
- const char* mName = m.strnstr(name.c_str(), m.fEnd);
- if (!mName) {
- return false;
- }
- m.skipTo(mName);
- while (!def.eof() && ')' != def.peek() && !m.eof() && ')' != m.peek()) {
- const char* ds = def.fChar;
- const char* ms = m.fChar;
- const char* de = def.anyOf(") \n");
- const char* me = m.anyOf(") \n");
- def.skipTo(de);
- m.skipTo(me);
- if (def.fChar - ds != m.fChar - ms) {
- return false;
- }
- if (strncmp(ds, ms, (int) (def.fChar - ds))) {
- return false;
- }
- def.skipWhiteSpace();
- m.skipWhiteSpace();
- }
- return !def.eof() && ')' == def.peek() && !m.eof() && ')' == m.peek();
-}
-
-void RootDefinition::clearVisited() {
- fVisited = false;
- for (auto& leaf : fLeaves) {
- leaf.second.fVisited = false;
- }
- for (auto& branch : fBranches) {
- branch.second->clearVisited();
- }
-}
-
-bool RootDefinition::dumpUnVisited() {
- bool allStructElementsFound = true;
- for (auto& leaf : fLeaves) {
- if (!leaf.second.fVisited) {
- // TODO: parse embedded struct in includeParser phase, then remove this condition
- if (FLAGS_skip) {
- const Definition& def = leaf.second;
- if (def.fChildren.size() > 0 &&
- MarkType::kDeprecated == def.fChildren[0]->fMarkType) {
- continue;
- }
- }
- SkDebugf("defined in bmh but missing in include: %s\n", leaf.first.c_str());
- }
- }
- for (auto& branch : fBranches) {
- allStructElementsFound &= branch.second->dumpUnVisited();
- }
- return allStructElementsFound;
-}
-
-const Definition* RootDefinition::find(const string& ref, AllowParens allowParens) const {
- const auto leafIter = fLeaves.find(ref);
- if (leafIter != fLeaves.end()) {
- return &leafIter->second;
- }
- if (AllowParens::kYes == allowParens && string::npos == ref.find("()")) {
- string withParens = ref + "()";
- const auto parensIter = fLeaves.find(withParens);
- if (parensIter != fLeaves.end()) {
- return &parensIter->second;
- }
- }
- const auto branchIter = fBranches.find(ref);
- if (branchIter != fBranches.end()) {
- const RootDefinition* rootDef = branchIter->second;
- return rootDef;
- }
- const Definition* result = nullptr;
- for (const auto& branch : fBranches) {
- const RootDefinition* rootDef = branch.second;
- result = rootDef->find(ref, allowParens);
- if (result) {
- break;
- }
- }
- return result;
-}
-
/*
class contains named struct, enum, enum-member, method, topic, subtopic
everything contained by class is uniquely named
@@ -982,7 +158,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
definition->fFiddle = name;
}
} else {
- definition->fFiddle = normalized_name(name);
+ definition->fFiddle = Definition::NormalizedName(name);
}
definition->fMarkType = markType;
definition->fAnonymous = fAnonymous;
@@ -1008,7 +184,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
parent = parent->fParent;
}
definition->fFiddle = parent ? parent->fFiddle + '_' : "";
- definition->fFiddle += normalized_name(typeNameBuilder[0]);
+ definition->fFiddle += Definition::NormalizedName(typeNameBuilder[0]);
this->setAsParent(definition);
}
{
@@ -1049,7 +225,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
definition->fStart = defStart;
definition->fContentStart = start;
definition->fName = name;
- definition->fFiddle = normalized_name(name);
+ definition->fFiddle = Definition::NormalizedName(name);
definition->fContentEnd = fChar;
this->skipToEndBracket('\n');
definition->fTerminator = fChar;
@@ -1121,6 +297,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
return this->reportError<bool>("missing example body");
}
}
+ definition->setWrapper();
}
} else {
fMarkup.emplace_front(markType, defStart, fLineCount, fParent);
@@ -1160,6 +337,8 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
case MarkType::kFile:
case MarkType::kHeight:
case MarkType::kImage:
+ case MarkType::kLiteral:
+ case MarkType::kOutdent:
case MarkType::kPlatform:
case MarkType::kSeeAlso:
case MarkType::kSubstitute:
@@ -1174,7 +353,7 @@ bool BmhParser::addDefinition(const char* defStart, bool hasEnd, MarkType markTy
fMarkup.emplace_front(markType, defStart, fLineCount, fParent);
definition = &fMarkup.front();
definition->fName = typeNameBuilder[0];
- definition->fFiddle = normalized_name(typeNameBuilder[0]);
+ definition->fFiddle = Definition::NormalizedName(typeNameBuilder[0]);
definition->fContentStart = fChar;
definition->fContentEnd = this->trimmedBracketEnd('\n');
definition->fTerminator = this->lineEnd() - 1;
@@ -1384,7 +563,7 @@ bool BmhParser::collectExternals() {
RootDefinition* definition = &fExternals.front();
definition->fFileName = fFileName;
definition->fName = string(wordStart ,fChar - wordStart);
- definition->fFiddle = normalized_name(definition->fName);
+ definition->fFiddle = Definition::NormalizedName(definition->fName);
}
} while (!this->eof());
return true;
@@ -1393,10 +572,12 @@ bool BmhParser::collectExternals() {
static bool dump_examples(FILE* fiddleOut, const Definition& def, bool* continuation) {
if (MarkType::kExample == def.fMarkType) {
string result;
- if (!def.exampleToScript(&result)) {
+ if (!def.exampleToScript(&result, Definition::ExampleOptions::kAll)) {
return false;
}
if (result.length() > 0) {
+ result += "\n";
+ result += "}";
if (*continuation) {
fprintf(fiddleOut, ",\n");
} else {
@@ -1601,7 +782,7 @@ bool BmhParser::findDefinitions() {
}
}
if (fParent) {
- return this->reportError<bool>("mismatched end");
+ return fParent->reportError<bool>("mismatched end");
}
return true;
}
@@ -1769,10 +950,20 @@ string BmhParser::methodName() {
}
builder = parent->fName + "::";
}
+ bool addConst = false;
if (isConstructor || expectOperator) {
paren = this->strnchr(')', end) + 1;
+ TextParser::Save saveState(this);
+ this->skipTo(paren);
+ if (this->skipExact("_const")) {
+ addConst = true;
+ }
+ saveState.restore();
}
builder.append(nameStart, paren - nameStart);
+ if (addConst) {
+ builder.append("_const");
+ }
if (!expectOperator && allLower) {
builder.append("()");
}
@@ -1968,7 +1159,6 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kEnumClass:
case MarkType::kClass:
case MarkType::kStruct:
- case MarkType::kTypedef:
// expect name
builder = this->className(markType);
break;
@@ -2001,6 +1191,8 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kFile:
case MarkType::kHeight:
case MarkType::kImage:
+ case MarkType::kLiteral:
+ case MarkType::kOutdent:
case MarkType::kPlatform:
case MarkType::kReturn:
case MarkType::kSeeAlso:
@@ -2020,6 +1212,9 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
case MarkType::kMethod:
builder = this->methodName();
break;
+ case MarkType::kTypedef:
+ builder = this->typedefName();
+ break;
case MarkType::kParam:
// fixme: expect camelCase
builder = this->word("", "");
@@ -2046,6 +1241,82 @@ vector<string> BmhParser::typeName(MarkType markType, bool* checkEnd) {
return result;
}
+string BmhParser::typedefName() {
+ if (this->hasEndToken()) {
+ if (!fParent || !fParent->fName.length()) {
+ return this->reportError<string>("missing parent typedef name");
+ }
+ SkASSERT(fMC == this->peek());
+ this->next();
+ SkASSERT(fMC == this->peek());
+ this->next();
+ SkASSERT(fMC != this->peek());
+ return fParent->fName;
+ }
+ // look for typedef as one of three forms:
+ // typedef return-type (*NAME)(params);
+ // typedef alias NAME;
+ // typedef std::function<alias> NAME;
+ string builder;
+ const char* end = this->doubleLF();
+ if (!end) {
+ end = fEnd;
+ }
+ const char* altEnd = this->strnstr("#Typedef ##", end);
+ if (altEnd) {
+ end = this->strnchr('\n', end);
+ }
+ if (!end) {
+ return this->reportError<string>("missing typedef std::function end bracket >");
+ }
+
+ if (this->startsWith("std::function")) {
+ if (!this->skipToEndBracket('>')) {
+ return this->reportError<string>("missing typedef std::function end bracket >");
+ }
+ this->next();
+ this->skipWhiteSpace();
+ builder = string(fChar, end - fChar);
+ } else {
+ const char* paren = this->strnchr('(', end);
+ if (!paren) {
+ const char* lastWord = nullptr;
+ do {
+ this->skipToWhiteSpace();
+ if (fChar < end && isspace(fChar[0])) {
+ this->skipWhiteSpace();
+ lastWord = fChar;
+ } else {
+ break;
+ }
+ } while (true);
+ if (!lastWord) {
+ return this->reportError<string>("missing typedef name");
+ }
+ builder = string(lastWord, end - lastWord);
+ } else {
+ this->skipTo(paren);
+ this->next();
+ if ('*' != this->next()) {
+ return this->reportError<string>("missing typedef function asterisk");
+ }
+ const char* nameStart = fChar;
+ if (!this->skipToEndBracket(')')) {
+ return this->reportError<string>("missing typedef function )");
+ }
+ builder = string(nameStart, fChar - nameStart);
+ if (!this->skipToEndBracket('(')) {
+ return this->reportError<string>("missing typedef params (");
+ }
+ if (! this->skipToEndBracket(')')) {
+ return this->reportError<string>("missing typedef params )");
+ }
+ this->skipTo(end);
+ }
+ }
+ return uniqueRootName(builder, MarkType::kTypedef);
+}
+
string BmhParser::uniqueName(const string& base, MarkType markType) {
string builder(base);
if (!builder.length()) {
@@ -2077,6 +1348,9 @@ string BmhParser::uniqueRootName(const string& base, MarkType markType) {
return markType == def.fMarkType && def.fName == numBuilder;
};
+ if (string::npos != base.find("SkMatrix::operator")) {
+ SkDebugf("");
+ }
string builder(base);
if (!builder.length()) {
builder = fParent->fName;
@@ -2115,6 +1389,9 @@ tryNext: ;
cloned->fCloned = true;
}
fCloned = true;
+ if (string::npos != builder.find("operator")) {
+ SkDebugf("");
+ }
numBuilder = builder + '_' + to_string(number);
} while (++number);
return numBuilder;
@@ -2200,11 +1477,11 @@ static int count_children(const Definition& def, MarkType markType) {
}
int main(int argc, char** const argv) {
- BmhParser bmhParser;
+ BmhParser bmhParser(FLAGS_skip);
bmhParser.validate();
SkCommandLineFlags::SetUsage(
- "Common Usage: bookmaker -i path/to/include.h -t\n"
+ "Common Usage: bookmaker -b path/to/bmh_files -i path/to/include.h -t\n"
" bookmaker -b path/to/bmh_files -e fiddle.json\n"
" ~/go/bin/fiddlecli --input fiddle.json --output fiddleout.json\n"
" bookmaker -b path/to/bmh_files -f fiddleout.json -r path/to/md_files\n"
@@ -2238,6 +1515,11 @@ int main(int argc, char** const argv) {
SkCommandLineFlags::PrintUsage();
return 1;
}
+ if ((FLAGS_bmh.isEmpty() || FLAGS_fiddle.isEmpty() || FLAGS_ref.isEmpty()) && FLAGS_catalog) {
+ SkDebugf("-c requires -b -f -r\n");
+ SkCommandLineFlags::PrintUsage();
+ return 1;
+ }
if (FLAGS_bmh.isEmpty() && !FLAGS_examples.isEmpty()) {
SkDebugf("-e requires -b\n");
SkCommandLineFlags::PrintUsage();
@@ -2271,8 +1553,8 @@ int main(int argc, char** const argv) {
SkCommandLineFlags::PrintUsage();
return 1;
}
- if (FLAGS_include.isEmpty() && !FLAGS_tokens.isEmpty()) {
- SkDebugf("-t requires -i\n");
+ if ((FLAGS_include.isEmpty() || FLAGS_bmh.isEmpty()) && FLAGS_tokens) {
+ SkDebugf("-t requires -b -i\n");
SkCommandLineFlags::PrintUsage();
return 1;
}
@@ -2282,21 +1564,22 @@ int main(int argc, char** const argv) {
return 1;
}
if (!FLAGS_bmh.isEmpty()) {
+ bmhParser.reset();
if (!bmhParser.parseFile(FLAGS_bmh[0], ".bmh")) {
return -1;
}
}
bool done = false;
if (!FLAGS_include.isEmpty()) {
- if (!FLAGS_tokens.isEmpty() || FLAGS_crosscheck) {
+ if (FLAGS_tokens || FLAGS_crosscheck) {
IncludeParser includeParser;
includeParser.validate();
if (!includeParser.parseFile(FLAGS_include[0], ".h")) {
return -1;
}
- if (!FLAGS_tokens.isEmpty()) {
+ if (FLAGS_tokens) {
includeParser.fDebugOut = FLAGS_stdout;
- if (includeParser.dumpTokens(FLAGS_tokens[0])) {
+ if (includeParser.dumpTokens(FLAGS_bmh[0])) {
bmhParser.fWroteOut = true;
}
done = true;
@@ -2320,12 +1603,27 @@ int main(int argc, char** const argv) {
done = true;
}
}
- FiddleParser fparser(&bmhParser);
- if (!done && !FLAGS_fiddle.isEmpty() && FLAGS_examples.isEmpty()) {
+ if (!done && !FLAGS_catalog && !FLAGS_fiddle.isEmpty() && FLAGS_examples.isEmpty()) {
+ FiddleParser fparser(&bmhParser);
if (!fparser.parseFile(FLAGS_fiddle[0], ".txt")) {
return -1;
}
}
+ if (!done && FLAGS_catalog && FLAGS_examples.isEmpty()) {
+ Catalog fparser(&bmhParser);
+ fparser.fDebugOut = FLAGS_stdout;
+ if (!fparser.openCatalog(FLAGS_bmh[0], FLAGS_ref[0])) {
+ return -1;
+ }
+ if (!fparser.parseFile(FLAGS_fiddle[0], ".txt")) {
+ return -1;
+ }
+ if (!fparser.closeCatalog()) {
+ return -1;
+ }
+ bmhParser.fWroteOut = true;
+ done = true;
+ }
if (!done && !FLAGS_ref.isEmpty() && FLAGS_examples.isEmpty()) {
MdOut mdOut(bmhParser);
mdOut.fDebugOut = FLAGS_stdout;
@@ -2335,6 +1633,7 @@ int main(int argc, char** const argv) {
}
if (!done && !FLAGS_spellcheck.isEmpty() && FLAGS_examples.isEmpty()) {
bmhParser.spellCheck(FLAGS_bmh[0], FLAGS_spellcheck);
+ bmhParser.fWroteOut = true;
done = true;
}
int examples = 0;
diff --git a/chromium/third_party/skia/tools/bookmaker/bookmaker.h b/chromium/third_party/skia/tools/bookmaker/bookmaker.h
index 857caf4c105..8cd128804c5 100644
--- a/chromium/third_party/skia/tools/bookmaker/bookmaker.h
+++ b/chromium/third_party/skia/tools/bookmaker/bookmaker.h
@@ -40,6 +40,7 @@ using std::vector;
enum class KeyWord {
kNone,
kSK_API,
+ kSK_BEGIN_REQUIRE_DENSE,
kBool,
kChar,
kClass,
@@ -107,10 +108,12 @@ enum class MarkType {
kLegend,
kLink,
kList,
+ kLiteral, // don't lookup hyperlinks, do substitution, etc
kMarkChar,
kMember,
kMethod,
kNoExample,
+ kOutdent,
kParam,
kPlatform,
kPrivate,
@@ -300,6 +303,33 @@ public:
return *loc;
}
+ const char* doubleLF() const {
+ int count = 0;
+ const char* ptr = fChar;
+ const char* doubleStart = nullptr;
+ while (ptr < fEnd) {
+ if ('\n' == ptr[0]) {
+ if (++count == 1) {
+ doubleStart = ptr;
+ } else {
+ return doubleStart;
+ }
+ } else if (' ' < ptr[0]) {
+ count = 0;
+ }
+ ++ptr;
+ }
+ return nullptr;
+ }
+
+ bool endsWith(const char* match) {
+ int matchLen = strlen(match);
+ if (matchLen > fChar - fLine) {
+ return false;
+ }
+ return !strncmp(fChar - matchLen, match, matchLen);
+ }
+
bool eof() const { return fChar >= fEnd; }
const char* lineEnd() const {
@@ -428,7 +458,7 @@ public:
// since a.b can't be found as a named definition
void skipFullName() {
while (fChar < fEnd && (isalnum(fChar[0])
- || '_' == fChar[0] || '-' == fChar[0]
+ || '_' == fChar[0] /* || '-' == fChar[0] */
|| (':' == fChar[0] && fChar +1 < fEnd && ':' == fChar[1]))) {
if (':' == fChar[0] && fChar +1 < fEnd && ':' == fChar[1]) {
fChar++;
@@ -465,6 +495,12 @@ public:
}
}
+ void skipToWhiteSpace() {
+ while (fChar < fEnd && ' ' < fChar[0]) {
+ fChar++;
+ }
+ }
+
bool skipName(const char* word) {
size_t len = strlen(word);
if (len <= (size_t) (fEnd - fChar) && !strncmp(word, fChar, len)) {
@@ -634,10 +670,11 @@ public:
for (int i = 0; i < 4; ++i) {
unicode <<= 4;
SkASSERT((reader[0] >= '0' && reader[0] <= '9') ||
- (reader[0] >= 'A' && reader[0] <= 'F'));
+ (reader[0] >= 'A' && reader[0] <= 'F') ||
+ (reader[0] >= 'a' && reader[0] <= 'f'));
int nibble = *reader++ - '0';
if (nibble > 9) {
- nibble = 'A'- '9' + 1;
+ nibble = (nibble & ~('a' - 'A')) - 'A' + '9' + 1;
}
unicode |= nibble;
}
@@ -679,6 +716,12 @@ public:
kYes
};
+ enum class ExampleOptions {
+ kText,
+ kPng,
+ kAll
+ };
+
enum class MethodType {
kNone,
kConstructor,
@@ -686,6 +729,26 @@ public:
kOperator,
};
+ enum class Operator {
+ kUnknown,
+ kAdd,
+ kAddTo,
+ kArray,
+ kCast,
+ kCopy,
+ kDelete,
+ kDereference,
+ kEqual,
+ kMinus,
+ kMove,
+ kMultiply,
+ kMultiplyBy,
+ kNew,
+ kNotEqual,
+ kSubtract,
+ kSubtractFrom,
+ };
+
Definition() {}
Definition(const char* start, const char* end, int line, Definition* parent)
@@ -735,116 +798,19 @@ public:
virtual RootDefinition* asRoot() { SkASSERT(0); return nullptr; }
virtual const RootDefinition* asRoot() const { SkASSERT(0); return nullptr; }
-
- bool boilerplateIfDef(Definition* parent) {
- const Definition& label = fTokens.front();
- if (Type::kWord != label.fType) {
- return false;
- }
- fName = string(label.fContentStart, label.fContentEnd - label.fContentStart);
- return true;
- }
-
- // todo: this is matching #ifndef SkXXX_DEFINED for no particular reason
- // it doesn't do anything useful with arbitrary input, e.g. #ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS
-// also doesn't know what to do with SK_REQUIRE_LOCAL_VAR()
- bool boilerplateDef(Definition* parent) {
- if (!this->boilerplateIfDef(parent)) {
- return false;
- }
- const char* s = fName.c_str();
- const char* e = strchr(s, '_');
- return true; // fixme: if this is trying to do something useful with define, do it here
- if (!e) {
- return false;
- }
- string prefix(s, e - s);
- const char* inName = strstr(parent->fName.c_str(), prefix.c_str());
- if (!inName) {
- return false;
- }
- if ('/' != inName[-1] && '\\' != inName[-1]) {
- return false;
- }
- if (strcmp(inName + prefix.size(), ".h")) {
- return false;
- }
- return true;
- }
+ bool boilerplateIfDef(Definition* parent);
+ bool boilerplateDef(Definition* parent);
bool boilerplateEndIf() {
return true;
}
bool checkMethod() const;
-
- void setCanonicalFiddle();
bool crossCheck2(const Definition& includeToken) const;
bool crossCheck(const Definition& includeToken) const;
bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const;
- bool exampleToScript(string* result) const;
-
- string extractText(TrimExtract trimExtract) const {
- string result;
- TextParser parser(fFileName, fContentStart, fContentEnd, fLineCount);
- int childIndex = 0;
- char mc = '#';
- while (parser.fChar < parser.fEnd) {
- if (TrimExtract::kYes == trimExtract && !parser.skipWhiteSpace()) {
- break;
- }
- if (parser.next() == mc) {
- if (parser.next() == mc) {
- if (parser.next() == mc) {
- mc = parser.next();
- }
- } else {
- // fixme : more work to do if # style comment is in text
- // if in method definition, could be alternate method name
- --parser.fChar;
- if (' ' < parser.fChar[0]) {
- if (islower(parser.fChar[0])) {
- result += '\n';
- parser.skipLine();
- } else {
- SkASSERT(isupper(parser.fChar[0]));
- parser.skipTo(fChildren[childIndex]->fTerminator);
- if (mc == parser.fChar[0] && mc == parser.fChar[1]) {
- parser.next();
- parser.next();
- }
- childIndex++;
- }
- } else {
- parser.skipLine();
- }
- continue;
- }
- } else {
- --parser.fChar;
- }
- const char* end = parser.fEnd;
- const char* mark = parser.strnchr(mc, end);
- if (mark) {
- end = mark;
- }
- string fragment(parser.fChar, end - parser.fChar);
- trim_end(fragment);
- if (TrimExtract::kYes == trimExtract) {
- trim_start(fragment);
- if (result.length()) {
- result += '\n';
- result += '\n';
- }
- }
- if (TrimExtract::kYes == trimExtract || has_nonwhitespace(fragment)) {
- result += fragment;
- }
- parser.skipTo(end);
- }
- return result;
- }
-
+ bool exampleToScript(string* result, ExampleOptions ) const;
+ string extractText(TrimExtract trimExtract) const;
string fiddleName() const;
string formatFunction() const;
const Definition* hasChild(MarkType markType) const;
@@ -872,7 +838,9 @@ public:
string methodName() const;
bool nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
string* paramName) const;
+ static string NormalizedName(string name);
bool paramsMatch(const string& fullRef, const string& name) const;
+ bool parseOperator(size_t doubleColons, string& result);
string printableName() const {
string result(fName);
@@ -887,11 +855,14 @@ public:
}
virtual RootDefinition* rootParent() { SkASSERT(0); return nullptr; }
+ void setCanonicalFiddle();
void setParentIndex() {
fParentIndex = fParent ? (int) fParent->fTokens.size() : -1;
}
+ void setWrapper();
+
string fText; // if text is constructed instead of in a file, it's put here
const char* fStart = nullptr; // .. in original text file, or the start of fText
const char* fContentStart; // start past optional markup name
@@ -904,6 +875,7 @@ public:
vector<Definition*> fChildren;
string fHash; // generated by fiddle
string fFileName;
+ mutable string fWrapper; // used by Example to wrap into proper function
size_t fLineCount = 0;
int fParentIndex = 0;
MarkType fMarkType = MarkType::kNone;
@@ -911,9 +883,11 @@ public:
Bracket fBracket = Bracket::kNone;
Punctuation fPunctuation = Punctuation::kNone;
MethodType fMethodType = MethodType::kNone;
+ Operator fOperator = Operator::kUnknown;
Type fType = Type::kNone;
bool fClone = false;
bool fCloned = false;
+ bool fOperatorConst = false;
bool fPrivate = false;
bool fShort = false;
bool fMemberStart = false;
@@ -948,7 +922,7 @@ public:
RootDefinition* asRoot() override { return this; }
const RootDefinition* asRoot() const override { return this; }
void clearVisited();
- bool dumpUnVisited();
+ bool dumpUnVisited(bool skip);
const Definition* find(const string& ref, AllowParens ) const;
bool isRoot() const override { return true; }
RootDefinition* rootParent() override { return fRootParent; }
@@ -1063,6 +1037,7 @@ public:
fMaxLF = 2;
fPendingLF = 0;
fPendingSpace = 0;
+ fOutdentNext = false;
nl();
}
@@ -1078,46 +1053,14 @@ public:
fMaxLF = 1;
}
- bool writeBlockTrim(int size, const char* data) {
- while (size && ' ' >= data[0]) {
- ++data;
- --size;
- }
- while (size && ' ' >= data[size - 1]) {
- --size;
- }
- if (size <= 0) {
- fLastChar = '\0';
- return false;
- }
- SkASSERT(size < 16000);
- if (size > 3 && !strncmp("#end", data, 4)) {
- fMaxLF = 1;
- }
- if (this->leadingPunctuation(data, (size_t) size)) {
- fPendingSpace = 0;
- }
- writePending();
- if (fDebugOut) {
- string check(data, size);
- SkDebugf("%s", check.c_str());
- }
- fprintf(fOut, "%.*s", size, data);
- int added = 0;
- fLastChar = data[size - 1];
- while (size > 0 && '\n' != data[--size]) {
- ++added;
- }
- fColumn = size ? added : fColumn + added;
- fSpaces = 0;
- fLinefeeds = 0;
- fMaxLF = added > 2 && !strncmp("#if", &data[size + (size > 0)], 3) ? 1 : 2;
- return true;
- }
void writeBlock(int size, const char* data) {
SkAssertResult(writeBlockTrim(size, data));
}
+
+ void writeBlockIndent(int size, const char* data);
+ bool writeBlockTrim(int size, const char* data);
+
void writeCommentHeader() {
this->lf(2);
this->writeString("/**");
@@ -1129,6 +1072,8 @@ public:
this->lfcr();
}
+ void writePending();
+
// write a pending space, so that two consecutive calls
// don't double write, and trailing spaces on lines aren't written
void writeSpace(int count = 1) {
@@ -1139,62 +1084,12 @@ public:
fPendingSpace = count;
}
- void writeString(const char* str) {
- const size_t len = strlen(str);
- SkASSERT(len > 0);
- SkASSERT(' ' < str[0]);
- fLastChar = str[len - 1];
- SkASSERT(' ' < fLastChar);
- SkASSERT(!strchr(str, '\n'));
- if (this->leadingPunctuation(str, strlen(str))) {
- fPendingSpace = 0;
- }
- writePending();
- if (fDebugOut) {
- SkDebugf("%s", str);
- }
- fprintf(fOut, "%s", str);
- fColumn += len;
- fSpaces = 0;
- fLinefeeds = 0;
- fMaxLF = 2;
- }
+ void writeString(const char* str);
void writeString(const string& str) {
this->writeString(str.c_str());
}
- void writePending() {
- fPendingLF = SkTMin(fPendingLF, fMaxLF);
- bool wroteLF = false;
- while (fLinefeeds < fPendingLF) {
- if (fDebugOut) {
- SkDebugf("\n");
- }
- fprintf(fOut, "\n");
- ++fLinefeeds;
- wroteLF = true;
- }
- fPendingLF = 0;
- if (wroteLF) {
- SkASSERT(0 == fColumn);
- SkASSERT(fIndent >= fSpaces);
- if (fDebugOut) {
- SkDebugf("%*s", fIndent - fSpaces, "");
- }
- fprintf(fOut, "%*s", fIndent - fSpaces, "");
- fColumn = fIndent;
- fSpaces = fIndent;
- }
- for (int index = 0; index < fPendingSpace; ++index) {
- if (fDebugOut) {
- SkDebugf(" ");
- }
- fprintf(fOut, " ");
- ++fColumn;
- }
- fPendingSpace = 0;
- }
unordered_map<string, sk_sp<SkData>> fRawData;
unordered_map<string, vector<char>> fLFOnly;
@@ -1209,6 +1104,7 @@ public:
int fPendingSpace; // one or two spaces should preceed the next string or block
char fLastChar; // last written
bool fDebugOut; // set true to write to std out
+ bool fOutdentNext; // set at end of embedded struct to prevent premature outdent
private:
typedef TextParser INHERITED;
};
@@ -1226,6 +1122,7 @@ public:
kNo, // neither resolved nor output
kYes, // resolved, output
kOut, // not resolved, but output
+ kLiteral, // output untouched (FIXME: is this really different from kOut?)
};
enum class Exemplary {
@@ -1258,7 +1155,7 @@ public:
#define E_N Exemplary::kNo
#define E_O Exemplary::kOptional
- BmhParser() : ParserCommon()
+ BmhParser(bool skip) : ParserCommon()
, fMaps {
// names without formal definitions (e.g. Column) aren't included
// fill in other names once they're actually used
@@ -1267,7 +1164,7 @@ public:
, { "Alias", nullptr, MarkType::kAlias, R_N, E_N, 0 }
, { "Bug", nullptr, MarkType::kBug, R_N, E_N, 0 }
, { "Class", &fClassMap, MarkType::kClass, R_Y, E_O, M_CSST | M(Root) }
-, { "Code", nullptr, MarkType::kCode, R_O, E_N, M_CSST | M_E }
+, { "Code", nullptr, MarkType::kCode, R_O, E_N, M_CSST | M_E | M(Method) }
, { "", nullptr, MarkType::kColumn, R_Y, E_N, M(Row) }
, { "", nullptr, MarkType::kComment, R_N, E_N, 0 }
, { "Const", &fConstMap, MarkType::kConst, R_Y, E_N, M_E | M_ST }
@@ -1291,10 +1188,12 @@ public:
, { "Legend", nullptr, MarkType::kLegend, R_Y, E_N, M(Table) }
, { "", nullptr, MarkType::kLink, R_N, E_N, M(Anchor) }
, { "List", nullptr, MarkType::kList, R_Y, E_N, M(Method) | M_CSST | M_E | M_D }
+, { "Literal", nullptr, MarkType::kLiteral, R_N, E_N, M(Code) }
, { "", nullptr, MarkType::kMarkChar, R_N, E_N, 0 }
, { "Member", nullptr, MarkType::kMember, R_Y, E_N, M(Class) | M(Struct) }
, { "Method", &fMethodMap, MarkType::kMethod, R_Y, E_Y, M_CSST }
, { "NoExample", nullptr, MarkType::kNoExample, R_Y, E_N, 0 }
+, { "Outdent", nullptr, MarkType::kOutdent, R_N, E_N, M(Code) }
, { "Param", nullptr, MarkType::kParam, R_Y, E_N, M(Method) }
, { "Platform", nullptr, MarkType::kPlatform, R_N, E_N, M(Example) }
, { "Private", nullptr, MarkType::kPrivate, R_N, E_N, 0 }
@@ -1313,10 +1212,11 @@ public:
, { "ToDo", nullptr, MarkType::kToDo, R_N, E_N, 0 }
, { "Topic", nullptr, MarkType::kTopic, R_Y, E_Y, M_CS | M(Root) | M(Topic) }
, { "Track", nullptr, MarkType::kTrack, R_Y, E_N, M_E | M_ST }
-, { "Typedef", &fTypedefMap, MarkType::kTypedef, R_Y, E_N, M(Subtopic) | M(Topic) }
+, { "Typedef", &fTypedefMap, MarkType::kTypedef, R_Y, E_N, M(Class) | M_ST }
, { "", nullptr, MarkType::kUnion, R_Y, E_N, 0 }
, { "Volatile", nullptr, MarkType::kVolatile, R_N, E_N, M(StdOut) }
, { "Width", nullptr, MarkType::kWidth, R_N, E_N, M(Example) } }
+, fSkip(skip)
{
this->reset();
}
@@ -1391,6 +1291,7 @@ public:
void spellCheck(const char* match, SkCommandLineFlags::StringArray report) const;
vector<string> topicName();
vector<string> typeName(MarkType markType, bool* expectEnd);
+ string typedefName();
string uniqueName(const string& base, MarkType markType);
string uniqueRootName(const string& base, MarkType markType);
void validate() const;
@@ -1432,6 +1333,7 @@ public:
bool fInComment;
bool fInString;
bool fCheckMethods;
+ bool fSkip = false;
bool fWroteOut = false;
private:
typedef ParserCommon INHERITED;
@@ -1474,10 +1376,12 @@ public:
, { nullptr, MarkType::kLegend }
, { nullptr, MarkType::kLink }
, { nullptr, MarkType::kList }
+ , { nullptr, MarkType::kLiteral }
, { nullptr, MarkType::kMarkChar }
, { nullptr, MarkType::kMember }
, { nullptr, MarkType::kMethod }
, { nullptr, MarkType::kNoExample }
+ , { nullptr, MarkType::kOutdent }
, { nullptr, MarkType::kParam }
, { nullptr, MarkType::kPlatform }
, { nullptr, MarkType::kPrivate }
@@ -1685,6 +1589,20 @@ public:
this->writeEndTag(tagType, tagID.c_str(), spaces);
}
+ void writeIncompleteTag(const char* tagType, const string& tagID, int spaces = 1) {
+ this->writeString(string("#") + tagType + " " + tagID);
+ this->writeSpace(spaces);
+ this->writeString("incomplete");
+ this->writeSpace();
+ this->writeString("##");
+ this->lf(1);
+ }
+
+ void writeIncompleteTag(const char* tagType) {
+ this->writeString(string("#") + tagType + " incomplete ##");
+ this->lf(1);
+ }
+
void writeTableHeader(const char* col1, size_t pad, const char* col2) {
this->lf(1);
this->writeString("#Table");
@@ -1757,6 +1675,7 @@ protected:
unordered_map<string, IClassDefinition> fIClassMap;
unordered_map<string, Definition> fIDefineMap;
unordered_map<string, Definition> fIEnumMap;
+ unordered_map<string, Definition> fIFunctionMap;
unordered_map<string, Definition> fIStructMap;
unordered_map<string, Definition> fITemplateMap;
unordered_map<string, Definition> fITypedefMap;
@@ -1824,7 +1743,10 @@ public:
const ParentPair* fPrev;
};
- IncludeWriter() : IncludeParser() {}
+ IncludeWriter() : IncludeParser() {
+ this->reset();
+ }
+
~IncludeWriter() override {}
bool contentFree(int size, const char* data) const {
@@ -1858,11 +1780,13 @@ public:
fBmhParser = nullptr;
fEnumDef = nullptr;
fMethodDef = nullptr;
- fStructDef = nullptr;
+ fBmhStructDef = nullptr;
fAttrDeprecated = nullptr;
fAnonymousEnumCount = 1;
fInStruct = false;
fWroteMethod = false;
+ fIndentNext = false;
+ fPendingMethod = false;
}
string resolveMethod(const char* start, const char* end, bool first);
@@ -1880,7 +1804,7 @@ private:
const Definition* fBmhMethod;
const Definition* fEnumDef;
const Definition* fMethodDef;
- const Definition* fStructDef;
+ const Definition* fBmhStructDef;
const Definition* fAttrDeprecated;
const char* fContinuation; // used to construct paren-qualified method name
int fAnonymousEnumCount;
@@ -1891,18 +1815,47 @@ private:
int fStructCommentTab;
bool fInStruct;
bool fWroteMethod;
+ bool fIndentNext;
+ bool fPendingMethod;
typedef IncludeParser INHERITED;
};
-class FiddleParser : public ParserCommon {
-public:
- FiddleParser(BmhParser* bmh) : ParserCommon()
- , fBmhParser(bmh) {
+class FiddleBase : public ParserCommon {
+protected:
+ FiddleBase(BmhParser* bmh) : ParserCommon()
+ , fBmhParser(bmh)
+ , fContinuation(false)
+ , fTextOut(false)
+ , fPngOut(false)
+ {
this->reset();
}
+ void reset() override {
+ INHERITED::resetCommon();
+ }
+
Definition* findExample(const string& name) const;
+ bool parseFiddles();
+ virtual bool pngOut(Definition* example) = 0;
+ virtual bool textOut(Definition* example, const char* stdOutStart,
+ const char* stdOutEnd) = 0;
+
+ BmhParser* fBmhParser; // must be writable; writes example hash
+ string fFullName;
+ bool fContinuation;
+ bool fTextOut;
+ bool fPngOut;
+private:
+ typedef ParserCommon INHERITED;
+};
+
+class FiddleParser : public FiddleBase {
+public:
+ FiddleParser(BmhParser* bmh) : FiddleBase(bmh) {
+ fTextOut = true;
+ }
bool parseFromFile(const char* path) override {
if (!INHERITED::parseSetup(path)) {
@@ -1911,16 +1864,34 @@ public:
return parseFiddles();
}
- void reset() override {
- INHERITED::resetCommon();
+private:
+ bool pngOut(Definition* example) override {
+ return true;
}
+ bool textOut(Definition* example, const char* stdOutStart,
+ const char* stdOutEnd) override;
+
+ typedef FiddleBase INHERITED;
+};
+
+class Catalog : public FiddleBase {
+public:
+ Catalog(BmhParser* bmh) : FiddleBase(bmh) {}
+
+ bool appendFile(const string& path);
+ bool closeCatalog();
+ bool openCatalog(const char* inDir, const char* outDir);
+
+ bool parseFromFile(const char* path) override ;
private:
- bool parseFiddles();
+ bool pngOut(Definition* example) override;
+ bool textOut(Definition* example, const char* stdOutStart,
+ const char* stdOutEnd) override;
- BmhParser* fBmhParser; // must be writable; writes example hash
+ string fDocsDir;
- typedef ParserCommon INHERITED;
+ typedef FiddleBase INHERITED;
};
class HackParser : public ParserCommon {
@@ -1986,9 +1957,18 @@ private:
fHasFiddle = false;
fInDescription = false;
fInList = false;
+ fRespectLeadingSpace = false;
}
- BmhParser::Resolvable resolvable(MarkType markType) {
+ BmhParser::Resolvable resolvable(const Definition* definition) const {
+ MarkType markType = definition->fMarkType;
+ if (MarkType::kCode == markType) {
+ for (auto child : definition->fChildren) {
+ if (MarkType::kLiteral == child->fMarkType) {
+ return BmhParser::Resolvable::kLiteral;
+ }
+ }
+ }
if ((MarkType::kExample == markType
|| MarkType::kFunction == markType) && fHasFiddle) {
return BmhParser::Resolvable::kNo;
@@ -2008,6 +1988,7 @@ private:
bool fInDescription; // FIXME: for now, ignore unfound camelCase in description since it may
// be defined in example which at present cannot be linked to
bool fInList;
+ bool fRespectLeadingSpace;
typedef ParserCommon INHERITED;
};
@@ -2044,10 +2025,11 @@ public:
}
}
if (this->startsWith(fClassName.c_str()) || this->startsWith("operator")) {
- const char* ptr = this->anyOf(" (");
+ const char* ptr = this->anyOf("\n (");
if (ptr && '(' == *ptr) {
this->skipToEndBracket(')');
SkAssertResult(')' == this->next());
+ this->skipExact("_const");
return;
}
}
@@ -2056,6 +2038,14 @@ public:
this->skipToNonAlphaNum();
} else {
this->skipFullName();
+ if (this->endsWith("operator")) {
+ const char* ptr = this->anyOf("\n (");
+ if (ptr && '(' == *ptr) {
+ this->skipToEndBracket(')');
+ SkAssertResult(')' == this->next());
+ this->skipExact("_const");
+ }
+ }
}
}
diff --git a/chromium/third_party/skia/tools/bookmaker/cataloger.cpp b/chromium/third_party/skia/tools/bookmaker/cataloger.cpp
new file mode 100644
index 00000000000..48e3b487534
--- /dev/null
+++ b/chromium/third_party/skia/tools/bookmaker/cataloger.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "bookmaker.h"
+
+#include "SkOSFile.h"
+#include "SkOSPath.h"
+
+bool Catalog::appendFile(const string& path) {
+ FILE* file = fopen(path.c_str(), "r");
+ if (!file) {
+ SkDebugf("could not append %s\n", path.c_str());
+ return false;
+ }
+ fseek(file, 0L, SEEK_END);
+ int sz = (int) ftell(file);
+ rewind(file);
+ char* buffer = new char[sz];
+ memset(buffer, ' ', sz);
+ SkAssertResult(sz == (int)fread(buffer, 1, sz, file));
+ fclose(file);
+ this->writeBlock(sz, buffer);
+ return true;
+}
+
+bool Catalog::openCatalog(const char* inDir, const char* outDir) {
+ fDocsDir = inDir;
+ if ('/' != fDocsDir.back()) {
+ fDocsDir += '/';
+ }
+ string outie = outDir;
+ if ('/' != outie.back()) {
+ outie += '/';
+ }
+ fFullName = outie + "catalog.htm";
+ fOut = fopen(fFullName.c_str(), "wb");
+ if (!fOut) {
+ SkDebugf("could not open output file %s\n", fFullName.c_str());
+ return false;
+ }
+ fContinuation = false;
+ if (!appendFile(fDocsDir + "catalogHeader.txt")) {
+ return false;
+ }
+ this->lf(1);
+ return true;
+}
+
+bool Catalog::closeCatalog() {
+ if (fOut) {
+ this->lf(1);
+ this->writeString("}");
+ this->lf(1);
+ if (!appendFile(fDocsDir + "catalogTrailer.txt")) {
+ return false;
+ }
+ this->lf(1);
+ this->writePending();
+ fclose(fOut);
+ SkDebugf("wrote %s\n", fFullName.c_str());
+ fOut = nullptr;
+ }
+ return true;
+}
+
+bool Catalog::parseFromFile(const char* path) {
+ if (!INHERITED::parseSetup(path)) {
+ return false;
+ }
+ fIndent = 4;
+ this->writeString("var text = {");
+ this->lf(1);
+ fTextOut = true;
+ TextParser::Save save(this);
+ if (!parseFiddles()) {
+ return false;
+ }
+ this->lf(1);
+ this->writeString("}");
+ this->lf(2);
+ this->writeString("var pngs = {");
+ fTextOut = false;
+ fPngOut = true;
+ save.restore();
+ fContinuation = false;
+ return parseFiddles();
+}
+
+bool Catalog::pngOut(Definition* example) {
+ string result;
+ if (!example->exampleToScript(&result, Definition::ExampleOptions::kPng)) {
+ return false;
+ }
+ if (result.length() > 0) {
+ if (fContinuation) {
+ this->writeString(",");
+ this->lf(1);
+ } else {
+ fContinuation = true;
+ }
+ this->writeBlock(result.size(), result.c_str());
+ }
+ return true;
+}
+
+bool Catalog::textOut(Definition* example, const char* stdOutStart,
+ const char* stdOutEnd) {
+ string result;
+ if (!example->exampleToScript(&result, Definition::ExampleOptions::kText)) {
+ return false;
+ }
+ if (result.length() > 0) {
+ if (fContinuation) {
+ this->writeString(",");
+ this->lf(1);
+ } else {
+ fContinuation = true;
+ }
+ fIndent = 8;
+ this->writeBlock(result.size(), result.c_str());
+ this->lf(1);
+ this->writeString("\"stdout\": \"");
+ size_t pos = 0;
+ size_t len = stdOutEnd - stdOutStart;
+ string example;
+ while ((size_t) pos < len) {
+ example += '"' == stdOutStart[pos] ? "\\\"" :
+ '\\' == stdOutStart[pos] ? "\\\\" :
+ string(&stdOutStart[pos], 1);
+ ++pos;
+ }
+ this->writeBlock(example.length(), example.c_str());
+ this->writeString("\"");
+ this->lf(1);
+ fIndent = 4;
+ this->writeString("}");
+ }
+ return true;
+}
diff --git a/chromium/third_party/skia/tools/bookmaker/definition.cpp b/chromium/third_party/skia/tools/bookmaker/definition.cpp
new file mode 100644
index 00000000000..44da2df2681
--- /dev/null
+++ b/chromium/third_party/skia/tools/bookmaker/definition.cpp
@@ -0,0 +1,1274 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "bookmaker.h"
+
+static size_t count_indent(const string& text, size_t test, size_t end) {
+ size_t result = test;
+ while (test < end) {
+ if (' ' != text[test]) {
+ break;
+ }
+ ++test;
+ }
+ return test - result;
+}
+
+static void add_code(const string& text, int pos, int end,
+ size_t outIndent, size_t textIndent, string& example) {
+ do {
+ // fix this to move whole paragraph in, out, but preserve doc indent
+ int nextIndent = count_indent(text, pos, end);
+ size_t len = text.find('\n', pos);
+ if (string::npos == len) {
+ len = end;
+ }
+ if ((size_t) (pos + nextIndent) < len) {
+ size_t indent = outIndent + nextIndent;
+ SkASSERT(indent >= textIndent);
+ indent -= textIndent;
+ for (size_t index = 0; index < indent; ++index) {
+ example += ' ';
+ }
+ pos += nextIndent;
+ while ((size_t) pos < len) {
+ example += '"' == text[pos] ? "\\\"" :
+ '\\' == text[pos] ? "\\\\" :
+ text.substr(pos, 1);
+ ++pos;
+ }
+ example += "\\n";
+ } else {
+ pos += nextIndent;
+ }
+ if ('\n' == text[pos]) {
+ ++pos;
+ }
+ } while (pos < end);
+}
+
+#ifdef CONST
+#undef CONST
+#endif
+
+#ifdef FRIEND
+#undef FRIEND
+#endif
+
+#ifdef BLANK
+#undef BLANK
+#endif
+
+#ifdef ANY
+#undef ANY
+#endif
+
+#ifdef DEFOP
+#undef DEFOP
+#endif
+
+#define CONST 1
+#define STATIC 2
+#define BLANK 0
+#define ANY -1
+#define DEFOP Definition::Operator
+
+enum class OpType : int8_t {
+ kNone,
+ kVoid,
+ kBool,
+ kChar,
+ kFloat,
+ kInt,
+ kScalar,
+ kSizeT,
+ kThis,
+ kAny,
+};
+
+enum class OpMod : int8_t {
+ kNone,
+ kArray,
+ kMove,
+ kPointer,
+ kReference,
+ kAny,
+};
+
+const struct OperatorParser {
+ DEFOP fOperator;
+ const char* fSymbol;
+ const char* fName;
+ int8_t fFriend;
+ OpType fReturnType;
+ OpMod fReturnMod;
+ int8_t fConstMethod;
+ struct Param {
+ int8_t fConst;
+ OpType fType;
+ OpMod fMod;
+ } fParams[2];
+} opData[] = {
+ { DEFOP::kUnknown, "??", "???", BLANK, OpType::kNone, OpMod::kNone, BLANK,
+ { } },
+ { DEFOP::kAdd, "+", "add", BLANK, OpType::kThis, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kAddTo, "+=", "addto", BLANK, OpType::kVoid, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kAddTo, "+=", "addto1", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kAddTo, "+=", "addto2", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ CONST, OpType::kChar, OpMod::kArray, }}},
+ { DEFOP::kAddTo, "+=", "addto3", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ CONST, OpType::kChar, OpMod::kNone, }}},
+ { DEFOP::kArray, "[]", "array", BLANK, OpType::kScalar, OpMod::kNone, CONST,
+ {{ BLANK, OpType::kInt, OpMod::kNone, }}},
+ { DEFOP::kArray, "[]", "array1", BLANK, OpType::kScalar, OpMod::kReference, BLANK,
+ {{ BLANK, OpType::kInt, OpMod::kNone, }}},
+ { DEFOP::kArray, "[]", "array2", BLANK, OpType::kChar, OpMod::kNone, CONST,
+ {{ BLANK, OpType::kSizeT, OpMod::kNone, }}},
+ { DEFOP::kArray, "[]", "array3", BLANK, OpType::kChar, OpMod::kReference, BLANK,
+ {{ BLANK, OpType::kSizeT, OpMod::kNone, }}},
+ { DEFOP::kCast, "()", "cast", BLANK, OpType::kAny, OpMod::kAny, ANY,
+ {{ ANY, OpType::kAny, OpMod::kAny, }}},
+ { DEFOP::kCopy, "=", "copy", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kCopy, "=", "copy1", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ CONST, OpType::kChar, OpMod::kArray, }}},
+ { DEFOP::kDelete, "delete", "delete", BLANK, OpType::kVoid, OpMod::kNone, BLANK,
+ {{ BLANK, OpType::kVoid, OpMod::kPointer, }}},
+ { DEFOP::kDereference, "->", "deref", ANY, OpType::kThis, OpMod::kPointer, CONST,
+ { } },
+ { DEFOP::kDereference, "*", "deref", BLANK, OpType::kThis, OpMod::kReference, CONST,
+ { } },
+ { DEFOP::kEqual, "==", "equal", BLANK, OpType::kBool, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kEqual, "==", "equal1", BLANK, OpType::kBool, OpMod::kNone, CONST,
+ {{ CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kEqual, "==", "equal2", ANY, OpType::kBool, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kMinus, "-", "minus", BLANK, OpType::kThis, OpMod::kNone, CONST,
+ { } },
+ { DEFOP::kMove, "=", "move", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ BLANK, OpType::kThis, OpMod::kMove, }}},
+ { DEFOP::kMultiply, "*", "multiply", BLANK, OpType::kThis, OpMod::kNone, CONST,
+ {{ BLANK, OpType::kScalar, OpMod::kNone, }}},
+ { DEFOP::kMultiply, "*", "multiply1", BLANK, OpType::kThis, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kMultiplyBy, "*=", "multiplyby", BLANK, OpType::kThis, OpMod::kReference, BLANK,
+ {{ BLANK, OpType::kScalar, OpMod::kNone, }}},
+ { DEFOP::kNew, "new", "new", BLANK, OpType::kVoid, OpMod::kPointer, BLANK,
+ {{ BLANK, OpType::kSizeT, OpMod::kNone, }}},
+ { DEFOP::kNotEqual, "!=", "notequal", BLANK, OpType::kBool, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kNotEqual, "!=", "notequal1", BLANK, OpType::kBool, OpMod::kNone, CONST,
+ {{ CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kNotEqual, "!=", "notequal2", ANY, OpType::kBool, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kSubtract, "-", "subtract", BLANK, OpType::kThis, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, },
+ { CONST, OpType::kThis, OpMod::kReference, }}},
+ { DEFOP::kSubtractFrom, "-=", "subtractfrom", BLANK, OpType::kVoid, OpMod::kNone, BLANK,
+ {{ CONST, OpType::kThis, OpMod::kReference, }}},
+};
+
+OpType lookup_type(const string& typeWord, const string& name) {
+ if (typeWord == name || (typeWord == "SkIVector" && name == "SkIPoint")
+ || (typeWord == "SkVector" && name == "SkPoint")) {
+ return OpType::kThis;
+ }
+ const char* keyWords[] = { "void", "bool", "char", "float", "int", "SkScalar", "size_t" };
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(keyWords); ++i) {
+ if (typeWord == keyWords[i]) {
+ return (OpType) (i + 1);
+ }
+ }
+ return OpType::kNone;
+}
+
+OpMod lookup_mod(TextParser& iParser) {
+ OpMod mod = OpMod::kNone;
+ if ('&' == iParser.peek()) {
+ mod = OpMod::kReference;
+ iParser.next();
+ if ('&' == iParser.peek()) {
+ mod = OpMod::kMove;
+ iParser.next();
+ }
+ } else if ('*' == iParser.peek()) {
+ mod = OpMod::kPointer;
+ iParser.next();
+ }
+ iParser.skipWhiteSpace();
+ return mod;
+}
+
+bool Definition::parseOperator(size_t doubleColons, string& result) {
+ const char operatorStr[] = "operator";
+ size_t opPos = fName.find(operatorStr, doubleColons);
+ if (string::npos == opPos) {
+ return false;
+ }
+ string className(fName, 0, doubleColons - 2);
+ TextParser iParser(fFileName, fStart, fContentStart, fLineCount);
+ SkAssertResult(iParser.skipWord("#Method"));
+ iParser.skipExact("SK_API");
+ iParser.skipWhiteSpace();
+ bool isStatic = iParser.skipExact("static");
+ iParser.skipWhiteSpace();
+ iParser.skipExact("SK_API");
+ iParser.skipWhiteSpace();
+ bool returnsConst = iParser.skipExact("const");
+ if (returnsConst) {
+ SkASSERT(0); // incomplete
+ }
+ SkASSERT(isStatic == false || returnsConst == false);
+ iParser.skipWhiteSpace();
+ const char* returnTypeStart = iParser.fChar;
+ iParser.skipToNonAlphaNum();
+ SkASSERT(iParser.fChar > returnTypeStart);
+ string returnType(returnTypeStart, iParser.fChar - returnTypeStart);
+ OpType returnOpType = lookup_type(returnType, className);
+ iParser.skipWhiteSpace();
+ OpMod returnMod = lookup_mod(iParser);
+ SkAssertResult(iParser.skipExact("operator"));
+ iParser.skipWhiteSpace();
+ fMethodType = Definition::MethodType::kOperator;
+ TextParser::Save save(&iParser);
+ for (auto parser : opData) {
+ save.restore();
+ if (!iParser.skipExact(parser.fSymbol)) {
+ continue;
+ }
+ iParser.skipWhiteSpace();
+ if ('(' != iParser.peek()) {
+ continue;
+ }
+ if (parser.fFriend != ANY && (parser.fFriend == STATIC) != isStatic) {
+ continue;
+ }
+ if (parser.fReturnType != OpType::kAny && parser.fReturnType != returnOpType) {
+ continue;
+ }
+ if (parser.fReturnMod != OpMod::kAny && parser.fReturnMod != returnMod) {
+ continue;
+ }
+ iParser.next(); // skip '('
+ iParser.skipWhiteSpace();
+ int parserCount = (parser.fParams[0].fType != OpType::kNone) +
+ (parser.fParams[1].fType != OpType::kNone);
+ bool countsMatch = true;
+ for (int pIndex = 0; pIndex < 2; ++pIndex) {
+ if (')' == iParser.peek()) {
+ countsMatch = pIndex == parserCount;
+ break;
+ }
+ if (',' == iParser.peek()) {
+ iParser.next();
+ iParser.skipWhiteSpace();
+ }
+ bool paramConst = iParser.skipExact("const");
+ if (parser.fParams[pIndex].fConst != ANY &&
+ paramConst != (parser.fParams[pIndex].fConst == CONST)) {
+ countsMatch = false;
+ break;
+ }
+ iParser.skipWhiteSpace();
+ const char* paramStart = iParser.fChar;
+ iParser.skipToNonAlphaNum();
+ SkASSERT(iParser.fChar > paramStart);
+ string paramType(paramStart, iParser.fChar - paramStart);
+ OpType paramOpType = lookup_type(paramType, className);
+ if (parser.fParams[pIndex].fType != OpType::kAny &&
+ parser.fParams[pIndex].fType != paramOpType) {
+ countsMatch = false;
+ break;
+ }
+ iParser.skipWhiteSpace();
+ OpMod paramMod = lookup_mod(iParser);
+ if (parser.fParams[pIndex].fMod != OpMod::kAny &&
+ parser.fParams[pIndex].fMod != paramMod) {
+ countsMatch = false;
+ break;
+ }
+ iParser.skipToNonAlphaNum();
+ if ('[' == iParser.peek()) {
+ paramMod = OpMod::kArray;
+ SkAssertResult(iParser.skipExact("[]"));
+ }
+ iParser.skipWhiteSpace();
+ }
+ if (!countsMatch) {
+ continue;
+ }
+ if (')' != iParser.peek()) {
+ continue;
+ }
+ iParser.next();
+ bool constMethod = iParser.skipExact("_const");
+ if (parser.fConstMethod != ANY && (parser.fConstMethod == CONST) != constMethod) {
+ continue;
+ }
+ result += parser.fName;
+ result += "_operator";
+ fOperator = parser.fOperator;
+ fOperatorConst = constMethod;
+ return true;
+ }
+ SkASSERT(0); // incomplete
+ return false;
+#if 0
+ if ('!' == fName[opPos]) {
+ SkASSERT('=' == fName[opPos + 1]);
+ result += "not_equal_operator";
+ } else if ('=' == fName[opPos]) {
+ if ('(' == fName[opPos + 1]) {
+ result += isMove ? "move_" : "copy_";
+ result += "assignment_operator";
+ } else {
+ SkASSERT('=' == fName[opPos + 1]);
+ result += "equal_operator";
+ }
+ } else if ('[' == fName[opPos]) {
+ result += "subscript_operator";
+ const char* end = fContentStart;
+ while (end > fStart && ' ' >= end[-1]) {
+ --end;
+ }
+ string constCheck(fStart, end - fStart);
+ size_t constPos = constCheck.rfind("const");
+ if (constCheck.length() == constPos + 5) {
+ result += "_const";
+ }
+ } else if ('*' == fName[opPos]) {
+ result += "multiply_operator";
+ } else if ('-' == fName[opPos]) {
+ result += "subtract_operator";
+ } else if ('+' == fName[opPos]) {
+ result += "add_operator";
+ } else {
+ SkASSERT(0); // todo: incomplete
+ }
+#endif
+ return true;
+}
+
+#undef CONST
+#undef FRIEND
+#undef BLANK
+#undef DEFOP
+
+bool Definition::boilerplateIfDef(Definition* parent) {
+ const Definition& label = fTokens.front();
+ if (Type::kWord != label.fType) {
+ return false;
+ }
+ fName = string(label.fContentStart, label.fContentEnd - label.fContentStart);
+ return true;
+}
+
+// todo: this is matching #ifndef SkXXX_DEFINED for no particular reason
+// it doesn't do anything useful with arbitrary input, e.g. #ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS
+// also doesn't know what to do with SK_REQUIRE_LOCAL_VAR()
+bool Definition::boilerplateDef(Definition* parent) {
+ if (!this->boilerplateIfDef(parent)) {
+ return false;
+ }
+ const char* s = fName.c_str();
+ const char* e = strchr(s, '_');
+ return true; // fixme: if this is trying to do something useful with define, do it here
+ if (!e) {
+ return false;
+ }
+ string prefix(s, e - s);
+ const char* inName = strstr(parent->fName.c_str(), prefix.c_str());
+ if (!inName) {
+ return false;
+ }
+ if ('/' != inName[-1] && '\\' != inName[-1]) {
+ return false;
+ }
+ if (strcmp(inName + prefix.size(), ".h")) {
+ return false;
+ }
+ return true;
+}
+
+// fixme: this will need to be more complicated to handle all of Skia
+// for now, just handle paint -- maybe fiddle will loosen naming restrictions
+void Definition::setCanonicalFiddle() {
+ fMethodType = Definition::MethodType::kNone;
+ size_t doubleColons = fName.find("::", 0);
+ SkASSERT(string::npos != doubleColons);
+ string base = fName.substr(0, doubleColons);
+ string result = base + "_";
+ doubleColons += 2;
+ if (string::npos != fName.find('~', doubleColons)) {
+ fMethodType = Definition::MethodType::kDestructor;
+ result += "destructor";
+ } else if (!this->parseOperator(doubleColons, result)) {
+ bool isMove = string::npos != fName.find("&&", doubleColons);
+ size_t parens = fName.find("()", doubleColons);
+ if (string::npos != parens) {
+ string methodName = fName.substr(doubleColons, parens - doubleColons);
+ do {
+ size_t nextDouble = methodName.find("::");
+ if (string::npos == nextDouble) {
+ break;
+ }
+ base = methodName.substr(0, nextDouble);
+ result += base + '_';
+ methodName = methodName.substr(nextDouble + 2);
+ doubleColons += nextDouble + 2;
+ } while (true);
+ if (base == methodName) {
+ fMethodType = Definition::MethodType::kConstructor;
+ result += "empty_constructor";
+ } else {
+ result += fName.substr(doubleColons, fName.length() - doubleColons - 2);
+ }
+ } else {
+ size_t openParen = fName.find('(', doubleColons);
+ if (string::npos == openParen) {
+ result += fName.substr(doubleColons);
+ } else {
+ size_t comma = fName.find(',', doubleColons);
+ if (string::npos == comma) {
+ result += isMove ? "move_" : "copy_";
+ }
+ fMethodType = Definition::MethodType::kConstructor;
+ // name them by their param types,
+ // e.g. SkCanvas__int_int_const_SkSurfaceProps_star
+ // TODO: move forward until parens are balanced and terminator =,)
+ TextParser params("", &fName[openParen] + 1, &*fName.end(), 0);
+ bool underline = false;
+ while (!params.eof()) {
+// SkDEBUGCODE(const char* end = params.anyOf("(),=")); // unused for now
+// SkASSERT(end[0] != '('); // fixme: put off handling nested parentheseses
+ if (params.startsWith("const") || params.startsWith("int")
+ || params.startsWith("Sk")) {
+ const char* wordStart = params.fChar;
+ params.skipToNonAlphaNum();
+ if (underline) {
+ result += '_';
+ } else {
+ underline = true;
+ }
+ result += string(wordStart, params.fChar - wordStart);
+ } else {
+ params.skipToNonAlphaNum();
+ }
+ if (!params.eof() && '*' == params.peek()) {
+ if (underline) {
+ result += '_';
+ } else {
+ underline = true;
+ }
+ result += "star";
+ params.next();
+ params.skipSpace();
+ }
+ params.skipToAlpha();
+ }
+ }
+ }
+ }
+ fFiddle = Definition::NormalizedName(result);
+}
+
+void Definition::setWrapper() {
+ const char drawWrapper[] = "void draw(SkCanvas* canvas) {";
+ const char drawNoCanvas[] = "void draw(SkCanvas* ) {";
+ string text = this->extractText(Definition::TrimExtract::kNo);
+ size_t nonSpace = 0;
+ while (nonSpace < text.length() && ' ' >= text[nonSpace]) {
+ ++nonSpace;
+ }
+ bool hasFunc = !text.compare(nonSpace, sizeof(drawWrapper) - 1, drawWrapper);
+ bool noCanvas = !text.compare(nonSpace, sizeof(drawNoCanvas) - 1, drawNoCanvas);
+ bool hasCanvas = string::npos != text.find("SkCanvas canvas");
+ SkASSERT(!hasFunc || !noCanvas);
+ bool preprocessor = text[0] == '#';
+ bool wrapCode = !hasFunc && !noCanvas && !preprocessor;
+ if (wrapCode) {
+ fWrapper = hasCanvas ? string(drawNoCanvas) : string(drawWrapper);
+ }
+}
+
+bool Definition::exampleToScript(string* result, ExampleOptions exampleOptions) const {
+ bool hasFiddle = true;
+ const Definition* platform = this->hasChild(MarkType::kPlatform);
+ if (platform) {
+ TextParser platParse(platform);
+ hasFiddle = !platParse.strnstr("!fiddle", platParse.fEnd);
+ }
+ if (!hasFiddle) {
+ *result = "";
+ return true;
+ }
+ string text = this->extractText(Definition::TrimExtract::kNo);
+ bool textOut = string::npos != text.find("SkDebugf(")
+ || string::npos != text.find("dump(")
+ || string::npos != text.find("dumpHex(");
+ string heightStr = "256";
+ string widthStr = "256";
+ string normalizedName(fFiddle);
+ string code;
+ string imageStr = "0";
+ for (auto const& iter : fChildren) {
+ switch (iter->fMarkType) {
+ case MarkType::kError:
+ result->clear();
+ return true;
+ case MarkType::kHeight:
+ heightStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
+ break;
+ case MarkType::kWidth:
+ widthStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
+ break;
+ case MarkType::kDescription:
+ // ignore for now
+ break;
+ case MarkType::kFunction: {
+ // emit this, but don't wrap this in draw()
+ string funcText(iter->fContentStart, iter->fContentEnd - iter->fContentStart - 1);
+ size_t pos = 0;
+ while (pos < funcText.length() && ' ' > funcText[pos]) {
+ ++pos;
+ }
+ size_t indent = count_indent(funcText, pos, funcText.length());
+ add_code(funcText, pos, funcText.length(), 0, indent, code);
+ code += "\\n";
+ } break;
+ case MarkType::kComment:
+ break;
+ case MarkType::kImage:
+ imageStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
+ break;
+ case MarkType::kToDo:
+ break;
+ case MarkType::kMarkChar:
+ case MarkType::kPlatform:
+ // ignore for now
+ break;
+ case MarkType::kStdOut:
+ textOut = true;
+ break;
+ default:
+ SkASSERT(0); // more coding to do
+ }
+ }
+ string textOutStr = textOut ? "true" : "false";
+ size_t pos = 0;
+ while (pos < text.length() && ' ' > text[pos]) {
+ ++pos;
+ }
+ size_t end = text.length();
+ size_t outIndent = 0;
+ size_t textIndent = count_indent(text, pos, end);
+ if ("MakeFromBackendTexture" == fName) {
+ SkDebugf("");
+ }
+ if (fWrapper.length() > 0) {
+ code += fWrapper;
+ code += "\\n";
+ outIndent = 4;
+ }
+ add_code(text, pos, end, outIndent, textIndent, code);
+ if (fWrapper.length() > 0) {
+ code += "}";
+ }
+ string example = "\"" + normalizedName + "\": {\n";
+ size_t nameStart = fFileName.find("\\", 0);
+ SkASSERT(string::npos != nameStart);
+ string baseFile = fFileName.substr(nameStart + 1, fFileName.length() - nameStart - 5);
+ if (ExampleOptions::kText == exampleOptions) {
+ example += " \"code\": \"" + code + "\",\n";
+ example += " \"hash\": \"" + fHash + "\",\n";
+ example += " \"file\": \"" + baseFile + "\",\n";
+ example += " \"name\": \"" + fName + "\",";
+ } else {
+ example += " \"code\": \"" + code + "\",\n";
+ if (ExampleOptions::kPng == exampleOptions) {
+ example += " \"width\": " + widthStr + ",\n";
+ example += " \"height\": " + heightStr + ",\n";
+ example += " \"hash\": \"" + fHash + "\",\n";
+ example += " \"file\": \"" + baseFile + "\",\n";
+ example += " \"name\": \"" + fName + "\"\n";
+ example += "}";
+ } else {
+ example += " \"options\": {\n";
+ example += " \"width\": " + widthStr + ",\n";
+ example += " \"height\": " + heightStr + ",\n";
+ example += " \"source\": " + imageStr + ",\n";
+ example += " \"srgb\": false,\n";
+ example += " \"f16\": false,\n";
+ example += " \"textOnly\": " + textOutStr + ",\n";
+ example += " \"animated\": false,\n";
+ example += " \"duration\": 0\n";
+ example += " },\n";
+ example += " \"fast\": true";
+ }
+ }
+ *result = example;
+ return true;
+}
+
+string Definition::extractText(TrimExtract trimExtract) const {
+ string result;
+ TextParser parser(fFileName, fContentStart, fContentEnd, fLineCount);
+ int childIndex = 0;
+ char mc = '#';
+ while (parser.fChar < parser.fEnd) {
+ if (TrimExtract::kYes == trimExtract && !parser.skipWhiteSpace()) {
+ break;
+ }
+ if (parser.next() == mc) {
+ if (parser.next() == mc) {
+ if (parser.next() == mc) {
+ mc = parser.next();
+ }
+ } else {
+ // fixme : more work to do if # style comment is in text
+ // if in method definition, could be alternate method name
+ --parser.fChar;
+ if (' ' < parser.fChar[0]) {
+ if (islower(parser.fChar[0])) {
+ result += '\n';
+ parser.skipLine();
+ } else {
+ SkASSERT(isupper(parser.fChar[0]));
+ parser.skipTo(fChildren[childIndex]->fTerminator);
+ if (mc == parser.fChar[0] && mc == parser.fChar[1]) {
+ parser.next();
+ parser.next();
+ }
+ childIndex++;
+ }
+ } else {
+ parser.skipLine();
+ }
+ continue;
+ }
+ } else {
+ --parser.fChar;
+ }
+ const char* end = parser.fEnd;
+ const char* mark = parser.strnchr(mc, end);
+ if (mark) {
+ end = mark;
+ }
+ string fragment(parser.fChar, end - parser.fChar);
+ trim_end(fragment);
+ if (TrimExtract::kYes == trimExtract) {
+ trim_start(fragment);
+ if (result.length()) {
+ result += '\n';
+ result += '\n';
+ }
+ }
+ if (TrimExtract::kYes == trimExtract || has_nonwhitespace(fragment)) {
+ result += fragment;
+ }
+ parser.skipTo(end);
+ }
+ return result;
+}
+
+static void space_pad(string* str) {
+ size_t len = str->length();
+ if (len == 0) {
+ return;
+ }
+ char last = (*str)[len - 1];
+ if ('~' == last || ' ' >= last) {
+ return;
+ }
+ *str += ' ';
+}
+
+//start here;
+// see if it possible to abstract this a little bit so it can
+// additionally be used to find params and return in method prototype that
+// does not have corresponding doxygen comments
+bool Definition::checkMethod() const {
+ SkASSERT(MarkType::kMethod == fMarkType);
+ // if method returns a value, look for a return child
+ // for each parameter, look for a corresponding child
+ const char* end = fContentStart;
+ while (end > fStart && ' ' >= end[-1]) {
+ --end;
+ }
+ TextParser methodParser(fFileName, fStart, end, fLineCount);
+ methodParser.skipWhiteSpace();
+ SkASSERT(methodParser.startsWith("#Method"));
+ methodParser.skipName("#Method");
+ methodParser.skipSpace();
+ string name = this->methodName();
+ if (MethodType::kNone == fMethodType && name.length() > 2 &&
+ "()" == name.substr(name.length() - 2)) {
+ name = name.substr(0, name.length() - 2);
+ }
+ bool expectReturn = this->methodHasReturn(name, &methodParser);
+ bool foundReturn = false;
+ bool foundException = false;
+ for (auto& child : fChildren) {
+ foundException |= MarkType::kDeprecated == child->fMarkType
+ || MarkType::kExperimental == child->fMarkType;
+ if (MarkType::kReturn != child->fMarkType) {
+ if (MarkType::kParam == child->fMarkType) {
+ child->fVisited = false;
+ }
+ continue;
+ }
+ if (!expectReturn) {
+ return methodParser.reportError<bool>("no #Return expected");
+ }
+ if (foundReturn) {
+ return methodParser.reportError<bool>("multiple #Return markers");
+ }
+ foundReturn = true;
+ }
+ if (expectReturn && !foundReturn && !foundException) {
+ return methodParser.reportError<bool>("missing #Return marker");
+ }
+ const char* paren = methodParser.strnchr('(', methodParser.fEnd);
+ if (!paren) {
+ return methodParser.reportError<bool>("missing #Method function definition");
+ }
+ const char* nextEnd = paren;
+ do {
+ string paramName;
+ methodParser.fChar = nextEnd + 1;
+ methodParser.skipSpace();
+ if (!this->nextMethodParam(&methodParser, &nextEnd, &paramName)) {
+ continue;
+ }
+ bool foundParam = false;
+ for (auto& child : fChildren) {
+ if (MarkType::kParam != child->fMarkType) {
+ continue;
+ }
+ if (paramName != child->fName) {
+ continue;
+ }
+ if (child->fVisited) {
+ return methodParser.reportError<bool>("multiple #Method param with same name");
+ }
+ child->fVisited = true;
+ if (foundParam) {
+ TextParser paramError(child);
+ return methodParser.reportError<bool>("multiple #Param with same name");
+ }
+ foundParam = true;
+
+ }
+ if (!foundParam && !foundException) {
+ return methodParser.reportError<bool>("no #Param found");
+ }
+ if (')' == nextEnd[0]) {
+ break;
+ }
+ } while (')' != nextEnd[0]);
+ for (auto& child : fChildren) {
+ if (MarkType::kParam != child->fMarkType) {
+ continue;
+ }
+ if (!child->fVisited) {
+ TextParser paramError(child);
+ return paramError.reportError<bool>("#Param without param in #Method");
+ }
+ }
+ return true;
+}
+
+bool Definition::crossCheck2(const Definition& includeToken) const {
+ TextParser parser(fFileName, fStart, fContentStart, fLineCount);
+ parser.skipExact("#");
+ bool isMethod = parser.skipName("Method");
+ const char* contentEnd;
+ if (isMethod) {
+ contentEnd = fContentStart;
+ } else if (parser.skipName("DefinedBy")) {
+ contentEnd = fContentEnd;
+ while (parser.fChar < contentEnd && ' ' >= contentEnd[-1]) {
+ --contentEnd;
+ }
+ if (parser.fChar < contentEnd - 1 && ')' == contentEnd[-1] && '(' == contentEnd[-2]) {
+ contentEnd -= 2;
+ }
+ } else {
+ return parser.reportError<bool>("unexpected crosscheck marktype");
+ }
+ return crossCheckInside(parser.fChar, contentEnd, includeToken);
+}
+
+bool Definition::crossCheck(const Definition& includeToken) const {
+ return crossCheckInside(fContentStart, fContentEnd, includeToken);
+}
+
+bool Definition::crossCheckInside(const char* start, const char* end,
+ const Definition& includeToken) const {
+ TextParser def(fFileName, start, end, fLineCount);
+ TextParser inc("", includeToken.fContentStart, includeToken.fContentEnd, 0);
+ if (inc.startsWith("SK_API")) {
+ inc.skipWord("SK_API");
+ }
+ if (inc.startsWith("friend")) {
+ inc.skipWord("friend");
+ }
+ if (inc.startsWith("SK_API")) {
+ inc.skipWord("SK_API");
+ }
+ inc.skipExact("SkDEBUGCODE(");
+ do {
+ bool defEof;
+ bool incEof;
+ do {
+ defEof = def.eof() || !def.skipWhiteSpace();
+ incEof = inc.eof() || !inc.skipWhiteSpace();
+ if (!incEof && '/' == inc.peek() && (defEof || '/' != def.peek())) {
+ inc.next();
+ if ('*' == inc.peek()) {
+ inc.skipToEndBracket("*/");
+ inc.next();
+ } else if ('/' == inc.peek()) {
+ inc.skipToEndBracket('\n');
+ }
+ } else if (!incEof && '#' == inc.peek() && (defEof || '#' != def.peek())) {
+ inc.next();
+ if (inc.startsWith("if")) {
+ inc.skipToEndBracket("\n");
+ } else if (inc.startsWith("endif")) {
+ inc.skipToEndBracket("\n");
+ } else {
+ SkASSERT(0); // incomplete
+ return false;
+ }
+ } else {
+ break;
+ }
+ inc.next();
+ } while (true);
+ if (defEof || incEof) {
+ if (defEof == incEof || (!defEof && ';' == def.peek())) {
+ return true;
+ }
+ return false; // allow setting breakpoint on failure
+ }
+ char defCh;
+ do {
+ defCh = def.next();
+ char incCh = inc.next();
+ if (' ' >= defCh && ' ' >= incCh) {
+ break;
+ }
+ if (defCh != incCh) {
+ if ('_' != defCh || ' ' != incCh || !fOperatorConst || !def.startsWith("const")) {
+ return false;
+ }
+ }
+ if (';' == defCh) {
+ return true;
+ }
+ } while (!def.eof() && !inc.eof());
+ } while (true);
+ return false;
+}
+
+string Definition::formatFunction() const {
+ const char* end = fContentStart;
+ while (end > fStart && ' ' >= end[-1]) {
+ --end;
+ }
+ TextParser methodParser(fFileName, fStart, end, fLineCount);
+ methodParser.skipWhiteSpace();
+ SkASSERT(methodParser.startsWith("#Method"));
+ methodParser.skipName("#Method");
+ methodParser.skipSpace();
+ const char* lastStart = methodParser.fChar;
+ const int limit = 100; // todo: allow this to be set by caller or in global or something
+ string name = this->methodName();
+ if ("MakeFromBackendTextureAsRenderTarget" == name) {
+ SkDebugf("");
+ }
+ const char* nameInParser = methodParser.strnstr(name.c_str(), methodParser.fEnd);
+ methodParser.skipTo(nameInParser);
+ const char* lastEnd = methodParser.fChar;
+ const char* paren = methodParser.strnchr('(', methodParser.fEnd);
+ size_t indent;
+ if (paren) {
+ indent = (size_t) (paren - lastStart) + 1;
+ } else {
+ indent = (size_t) (lastEnd - lastStart);
+ }
+ // trim indent so longest line doesn't exceed box width
+ TextParser::Save savePlace(&methodParser);
+ const char* saveStart = lastStart;
+ ptrdiff_t maxLine = 0;
+ do {
+ const char* nextStart = lastEnd;
+ const char* delimiter = methodParser.anyOf(",)");
+ const char* nextEnd = delimiter ? delimiter : methodParser.fEnd;
+ if (delimiter) {
+ while (nextStart < nextEnd && ' ' >= nextStart[0]) {
+ ++nextStart;
+ }
+ }
+ while (nextEnd > nextStart && ' ' >= nextEnd[-1]) {
+ --nextEnd;
+ }
+ if (delimiter) {
+ nextEnd += 1;
+ delimiter += 1;
+ }
+ if (lastEnd > lastStart) {
+ maxLine = SkTMax(maxLine, lastEnd - lastStart);
+ }
+ if (delimiter) {
+ methodParser.skipTo(delimiter);
+ }
+ lastStart = nextStart;
+ lastEnd = nextEnd;
+ } while (lastStart < lastEnd);
+ savePlace.restore();
+ lastStart = saveStart;
+ lastEnd = methodParser.fChar;
+ indent = SkTMin(indent, (size_t) (limit - maxLine));
+ // write string wtih trimmmed indent
+ string methodStr;
+ int written = 0;
+ do {
+ const char* nextStart = lastEnd;
+ SkASSERT(written < limit);
+ const char* delimiter = methodParser.anyOf(",)");
+ const char* nextEnd = delimiter ? delimiter : methodParser.fEnd;
+ if (delimiter) {
+ while (nextStart < nextEnd && ' ' >= nextStart[0]) {
+ ++nextStart;
+ }
+ }
+ while (nextEnd > nextStart && ' ' >= nextEnd[-1]) {
+ --nextEnd;
+ }
+ if (delimiter) {
+ nextEnd += 1;
+ delimiter += 1;
+ }
+ if (lastEnd > lastStart) {
+ if (lastStart[0] != ' ') {
+ space_pad(&methodStr);
+ }
+ methodStr += string(lastStart, (size_t) (lastEnd - lastStart));
+ written += (size_t) (lastEnd - lastStart);
+ }
+ if (delimiter) {
+ if (nextEnd - nextStart >= (ptrdiff_t) (limit - written)) {
+ written = indent;
+ methodStr += '\n';
+ methodStr += string(indent, ' ');
+ }
+ methodParser.skipTo(delimiter);
+ }
+ lastStart = nextStart;
+ lastEnd = nextEnd;
+ } while (lastStart < lastEnd);
+ return methodStr;
+}
+
+string Definition::fiddleName() const {
+ string result;
+ size_t start = 0;
+ string parent;
+ const Definition* parentDef = this;
+ while ((parentDef = parentDef->fParent)) {
+ if (MarkType::kClass == parentDef->fMarkType || MarkType::kStruct == parentDef->fMarkType) {
+ parent = parentDef->fFiddle;
+ break;
+ }
+ }
+ if (parent.length() && 0 == fFiddle.compare(0, parent.length(), parent)) {
+ start = parent.length();
+ while (start < fFiddle.length() && '_' == fFiddle[start]) {
+ ++start;
+ }
+ }
+ size_t end = fFiddle.find_first_of('(', start);
+ return fFiddle.substr(start, end - start);
+}
+
+const Definition* Definition::hasChild(MarkType markType) const {
+ for (auto iter : fChildren) {
+ if (markType == iter->fMarkType) {
+ return iter;
+ }
+ }
+ return nullptr;
+}
+
+const Definition* Definition::hasParam(const string& ref) const {
+ SkASSERT(MarkType::kMethod == fMarkType);
+ for (auto iter : fChildren) {
+ if (MarkType::kParam != iter->fMarkType) {
+ continue;
+ }
+ if (iter->fName == ref) {
+ return &*iter;
+ }
+
+ }
+ return nullptr;
+}
+
+bool Definition::methodHasReturn(const string& name, TextParser* methodParser) const {
+ if (methodParser->skipExact("static")) {
+ methodParser->skipWhiteSpace();
+ }
+ const char* lastStart = methodParser->fChar;
+ const char* nameInParser = methodParser->strnstr(name.c_str(), methodParser->fEnd);
+ methodParser->skipTo(nameInParser);
+ const char* lastEnd = methodParser->fChar;
+ const char* returnEnd = lastEnd;
+ while (returnEnd > lastStart && ' ' == returnEnd[-1]) {
+ --returnEnd;
+ }
+ bool expectReturn = 4 != returnEnd - lastStart || strncmp("void", lastStart, 4);
+ if (MethodType::kNone != fMethodType && MethodType::kOperator != fMethodType && !expectReturn) {
+ return methodParser->reportError<bool>("unexpected void");
+ }
+ switch (fMethodType) {
+ case MethodType::kNone:
+ case MethodType::kOperator:
+ // either is fine
+ break;
+ case MethodType::kConstructor:
+ expectReturn = true;
+ break;
+ case MethodType::kDestructor:
+ expectReturn = false;
+ break;
+ }
+ return expectReturn;
+}
+
+string Definition::methodName() const {
+ string result;
+ size_t start = 0;
+ string parent;
+ const Definition* parentDef = this;
+ while ((parentDef = parentDef->fParent)) {
+ if (MarkType::kClass == parentDef->fMarkType || MarkType::kStruct == parentDef->fMarkType) {
+ parent = parentDef->fName;
+ break;
+ }
+ }
+ if (parent.length() && 0 == fName.compare(0, parent.length(), parent)) {
+ start = parent.length();
+ while (start < fName.length() && ':' == fName[start]) {
+ ++start;
+ }
+ }
+ if (fClone) {
+ int lastUnder = fName.rfind('_');
+ return fName.substr(start, (size_t) (lastUnder - start));
+ }
+ size_t end = fName.find_first_of('(', start);
+ if (string::npos == end) {
+ return fName.substr(start);
+ }
+ return fName.substr(start, end - start);
+}
+
+bool Definition::nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
+ string* paramName) const {
+ int parenCount = 0;
+ TextParser::Save saveState(methodParser);
+ while (true) {
+ if (methodParser->eof()) {
+ return methodParser->reportError<bool>("#Method function missing close paren");
+ }
+ char ch = methodParser->peek();
+ if ('(' == ch) {
+ ++parenCount;
+ }
+ if (parenCount == 0 && (')' == ch || ',' == ch)) {
+ *nextEndPtr = methodParser->fChar;
+ break;
+ }
+ if (')' == ch) {
+ if (0 > --parenCount) {
+ return this->reportError<bool>("mismatched parentheses");
+ }
+ }
+ methodParser->next();
+ }
+ saveState.restore();
+ const char* nextEnd = *nextEndPtr;
+ const char* paramEnd = nextEnd;
+ const char* assign = methodParser->strnstr(" = ", paramEnd);
+ if (assign) {
+ paramEnd = assign;
+ }
+ const char* closeBracket = methodParser->strnstr("]", paramEnd);
+ if (closeBracket) {
+ const char* openBracket = methodParser->strnstr("[", paramEnd);
+ if (openBracket && openBracket < closeBracket) {
+ while (openBracket < --closeBracket && isdigit(closeBracket[0]))
+ ;
+ if (openBracket == closeBracket) {
+ paramEnd = openBracket;
+ }
+ }
+ }
+ const char* function = methodParser->strnstr(")(", paramEnd);
+ if (function) {
+ paramEnd = function;
+ }
+ while (paramEnd > methodParser->fChar && ' ' == paramEnd[-1]) {
+ --paramEnd;
+ }
+ const char* paramStart = paramEnd;
+ while (paramStart > methodParser->fChar && isalnum(paramStart[-1])) {
+ --paramStart;
+ }
+ if (paramStart > methodParser->fChar && paramStart >= paramEnd) {
+ return methodParser->reportError<bool>("#Method missing param name");
+ }
+ *paramName = string(paramStart, paramEnd - paramStart);
+ if (!paramName->length()) {
+ if (')' != nextEnd[0]) {
+ return methodParser->reportError<bool>("#Method malformed param");
+ }
+ return false;
+ }
+ return true;
+}
+
+string Definition::NormalizedName(string name) {
+ string normalizedName = name;
+ std::replace(normalizedName.begin(), normalizedName.end(), '-', '_');
+ do {
+ size_t doubleColon = normalizedName.find("::", 0);
+ if (string::npos == doubleColon) {
+ break;
+ }
+ normalizedName = normalizedName.substr(0, doubleColon)
+ + '_' + normalizedName.substr(doubleColon + 2);
+ } while (true);
+ return normalizedName;
+}
+
+bool Definition::paramsMatch(const string& match, const string& name) const {
+ TextParser def(fFileName, fStart, fContentStart, fLineCount);
+ const char* dName = def.strnstr(name.c_str(), fContentStart);
+ if (!dName) {
+ return false;
+ }
+ def.skipTo(dName);
+ TextParser m(fFileName, &match.front(), &match.back() + 1, fLineCount);
+ const char* mName = m.strnstr(name.c_str(), m.fEnd);
+ if (!mName) {
+ return false;
+ }
+ m.skipTo(mName);
+ while (!def.eof() && ')' != def.peek() && !m.eof() && ')' != m.peek()) {
+ const char* ds = def.fChar;
+ const char* ms = m.fChar;
+ const char* de = def.anyOf(") \n");
+ const char* me = m.anyOf(") \n");
+ def.skipTo(de);
+ m.skipTo(me);
+ if (def.fChar - ds != m.fChar - ms) {
+ return false;
+ }
+ if (strncmp(ds, ms, (int) (def.fChar - ds))) {
+ return false;
+ }
+ def.skipWhiteSpace();
+ m.skipWhiteSpace();
+ }
+ return !def.eof() && ')' == def.peek() && !m.eof() && ')' == m.peek();
+}
+
+void RootDefinition::clearVisited() {
+ fVisited = false;
+ for (auto& leaf : fLeaves) {
+ leaf.second.fVisited = false;
+ }
+ for (auto& branch : fBranches) {
+ branch.second->clearVisited();
+ }
+}
+
+bool RootDefinition::dumpUnVisited(bool skip) {
+ bool allStructElementsFound = true;
+ for (auto& leaf : fLeaves) {
+ if (!leaf.second.fVisited) {
+ // TODO: parse embedded struct in includeParser phase, then remove this condition
+ if (skip) {
+ const Definition& def = leaf.second;
+ if (def.fChildren.size() > 0 &&
+ MarkType::kDeprecated == def.fChildren[0]->fMarkType) {
+ continue;
+ }
+ }
+ // FIXME: bugs requiring long tail fixes, suppressed here:
+ // SkBitmap::validate() is wrapped in SkDEBUGCODE in .h and not parsed
+ if ("SkBitmap::validate()" == leaf.first) {
+ continue;
+ }
+ // typedef uint32_t SaveLayerFlags not seen in SkCanvas.h, don't know why
+ if ("SaveLayerFlags" == leaf.first) {
+ continue;
+ }
+ // SkPath::pathRefIsValid in #ifdef ; prefer to remove chrome dependency to fix
+ if ("SkPath::pathRefIsValid" == leaf.first) {
+ continue;
+ }
+ // FIXME: end of long tail bugs
+ SkDebugf("defined in bmh but missing in include: %s\n", leaf.first.c_str());
+ }
+ }
+ for (auto& branch : fBranches) {
+ allStructElementsFound &= branch.second->dumpUnVisited(skip);
+ }
+ return allStructElementsFound;
+}
+
+const Definition* RootDefinition::find(const string& ref, AllowParens allowParens) const {
+ const auto leafIter = fLeaves.find(ref);
+ if (leafIter != fLeaves.end()) {
+ return &leafIter->second;
+ }
+ if (AllowParens::kYes == allowParens && string::npos == ref.find("()")) {
+ string withParens = ref + "()";
+ const auto parensIter = fLeaves.find(withParens);
+ if (parensIter != fLeaves.end()) {
+ return &parensIter->second;
+ }
+ }
+ const auto branchIter = fBranches.find(ref);
+ if (branchIter != fBranches.end()) {
+ const RootDefinition* rootDef = branchIter->second;
+ return rootDef;
+ }
+ const Definition* result = nullptr;
+ for (const auto& branch : fBranches) {
+ const RootDefinition* rootDef = branch.second;
+ result = rootDef->find(ref, allowParens);
+ if (result) {
+ break;
+ }
+ }
+ return result;
+}
diff --git a/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp b/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp
index 33615433016..faf551006f7 100644
--- a/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/fiddleParser.cpp
@@ -20,7 +20,7 @@ static Definition* find_fiddle(Definition* def, const string& name) {
return nullptr;
}
-Definition* FiddleParser::findExample(const string& name) const {
+Definition* FiddleBase::findExample(const string& name) const {
for (const auto& topic : fBmhParser->fTopicMap) {
if (topic.second->fParent) {
continue;
@@ -33,7 +33,7 @@ Definition* FiddleParser::findExample(const string& name) const {
return nullptr;
}
-bool FiddleParser::parseFiddles() {
+bool FiddleBase::parseFiddles() {
if (!this->skipExact("{\n")) {
return false;
}
@@ -110,50 +110,15 @@ bool FiddleParser::parseFiddles() {
}
} while (!this->eof() && this->next());
const char* stdOutEnd = fChar;
- if (example) {
- bool foundStdOut = false;
- for (auto& textOut : example->fChildren) {
- if (MarkType::kStdOut != textOut->fMarkType) {
- continue;
- }
- foundStdOut = true;
- bool foundVolatile = false;
- for (auto& stdOutChild : textOut->fChildren) {
- if (MarkType::kVolatile == stdOutChild->fMarkType) {
- foundVolatile = true;
- break;
- }
- }
- TextParser bmh(textOut);
- EscapeParser fiddle(stdOutStart, stdOutEnd);
- do {
- bmh.skipWhiteSpace();
- fiddle.skipWhiteSpace();
- const char* bmhEnd = bmh.trimmedLineEnd();
- const char* fiddleEnd = fiddle.trimmedLineEnd();
- ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
- SkASSERT(bmhLen > 0);
- ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
- SkASSERT(fiddleLen > 0);
- if (bmhLen != fiddleLen) {
- if (!foundVolatile) {
- bmh.reportError("mismatched stdout len\n");
- }
- } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
- if (!foundVolatile) {
- bmh.reportError("mismatched stdout text\n");
- }
- }
- bmh.skipToLineStart();
- fiddle.skipToLineStart();
- } while (!bmh.eof() && !fiddle.eof());
- if (!foundStdOut) {
- bmh.reportError("bmh %s missing stdout\n");
- } else if (!bmh.eof() || !fiddle.eof()) {
- if (!foundVolatile) {
- bmh.reportError("%s mismatched stdout eof\n");
- }
- }
+ if (example && fTextOut) {
+ if (!this->textOut(example, stdOutStart, stdOutEnd)) {
+ return false;
+ }
+ }
+ } else {
+ if (example && fPngOut) {
+ if (!this->pngOut(example)) {
+ return false;
}
}
}
@@ -170,58 +135,54 @@ bool FiddleParser::parseFiddles() {
return false;
}
}
-#if 0
- // compare the text output with the expected output in the markup tree
- this->skipToSpace();
- SkASSERT(' ' == fChar[0]);
- this->next();
- const char* nameLoc = fChar;
- this->skipToNonAlphaNum();
- const char* nameEnd = fChar;
- string name(nameLoc, nameEnd - nameLoc);
- const Definition* example = this->findExample(name);
- if (!example) {
- return this->reportError<bool>("missing stdout name");
- }
- SkASSERT(':' == fChar[0]);
- this->next();
- this->skipSpace();
- const char* stdOutLoc = fChar;
- do {
- this->skipToLineStart();
- } while (!this->eof() && !this->startsWith("fiddles.htm:"));
- const char* stdOutEnd = fChar;
- for (auto& textOut : example->fChildren) {
- if (MarkType::kStdOut != textOut->fMarkType) {
- continue;
+ return true;
+}
+
+bool FiddleParser::textOut(Definition* example, const char* stdOutStart,
+ const char* stdOutEnd) {
+ bool foundStdOut = false;
+ for (auto& textOut : example->fChildren) {
+ if (MarkType::kStdOut != textOut->fMarkType) {
+ continue;
+ }
+ foundStdOut = true;
+ bool foundVolatile = false;
+ for (auto& stdOutChild : textOut->fChildren) {
+ if (MarkType::kVolatile == stdOutChild->fMarkType) {
+ foundVolatile = true;
+ break;
}
- TextParser bmh(textOut);
- TextParser fiddle(fFileName, stdOutLoc, stdOutEnd, fLineCount);
- do {
- bmh.skipWhiteSpace();
- fiddle.skipWhiteSpace();
- const char* bmhEnd = bmh.trimmedLineEnd();
- const char* fiddleEnd = fiddle.trimmedLineEnd();
- ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
- SkASSERT(bmhLen > 0);
- ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
- SkASSERT(fiddleLen > 0);
- if (bmhLen != fiddleLen) {
- return this->reportError<bool>("mismatched stdout len");
- }
- if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
- return this->reportError<bool>("mismatched stdout text");
- }
- bmh.skipToLineStart();
- fiddle.skipToLineStart();
- } while (!bmh.eof() && !fiddle.eof());
- if (!bmh.eof() || (!fiddle.eof() && !fiddle.startsWith("</pre>"))) {
- return this->reportError<bool>("mismatched stdout eof");
+ }
+ TextParser bmh(textOut);
+ EscapeParser fiddle(stdOutStart, stdOutEnd);
+ do {
+ bmh.skipWhiteSpace();
+ fiddle.skipWhiteSpace();
+ const char* bmhEnd = bmh.trimmedLineEnd();
+ const char* fiddleEnd = fiddle.trimmedLineEnd();
+ ptrdiff_t bmhLen = bmhEnd - bmh.fChar;
+ SkASSERT(bmhLen > 0);
+ ptrdiff_t fiddleLen = fiddleEnd - fiddle.fChar;
+ SkASSERT(fiddleLen > 0);
+ if (bmhLen != fiddleLen) {
+ if (!foundVolatile) {
+ bmh.reportError("mismatched stdout len\n");
+ }
+ } else if (strncmp(bmh.fChar, fiddle.fChar, fiddleLen)) {
+ if (!foundVolatile) {
+ bmh.reportError("mismatched stdout text\n");
}
- break;
+ }
+ bmh.skipToLineStart();
+ fiddle.skipToLineStart();
+ } while (!bmh.eof() && !fiddle.eof());
+ if (!foundStdOut) {
+ bmh.reportError("bmh %s missing stdout\n");
+ } else if (!bmh.eof() || !fiddle.eof()) {
+ if (!foundVolatile) {
+ bmh.reportError("%s mismatched stdout eof\n");
}
}
}
-#endif
return true;
}
diff --git a/chromium/third_party/skia/tools/bookmaker/includeParser.cpp b/chromium/third_party/skia/tools/bookmaker/includeParser.cpp
index 4ad83d8aa7e..955e6ef724e 100644
--- a/chromium/third_party/skia/tools/bookmaker/includeParser.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/includeParser.cpp
@@ -10,6 +10,7 @@
const IncludeKey kKeyWords[] = {
{ "", KeyWord::kNone, KeyProperty::kNone },
{ "SK_API", KeyWord::kSK_API, KeyProperty::kModifier },
+ { "SK_BEGIN_REQUIRE_DENSE", KeyWord::kSK_BEGIN_REQUIRE_DENSE, KeyProperty::kModifier },
{ "bool", KeyWord::kBool, KeyProperty::kNumber },
{ "char", KeyWord::kChar, KeyProperty::kNumber },
{ "class", KeyWord::kClass, KeyProperty::kObject },
@@ -105,7 +106,7 @@ void IncludeParser::checkForMissingParams(const vector<string>& methodParams,
}
}
if (!found) {
- this->writeEndTag("Param", methodParam, 2);
+ this->writeIncompleteTag("Param", methodParam, 2);
}
}
for (auto& foundParam : foundParams) {
@@ -438,7 +439,7 @@ bool IncludeParser::crossCheck(BmhParser& bmhParser) {
continue;
}
RootDefinition* root = &finder->second;
- if (!root->dumpUnVisited()) {
+ if (!root->dumpUnVisited(bmhParser.fSkip)) {
SkDebugf("some struct elements not found; struct finding in includeParser is missing\n");
}
SkDebugf("cross-checked %s\n", className.c_str());
@@ -494,6 +495,7 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) {
}
switch (token.fMarkType) {
case MarkType::kEnum:
+ case MarkType::kEnumClass:
this->dumpEnum(token);
break;
case MarkType::kMethod:
@@ -508,11 +510,30 @@ void IncludeParser::dumpClassTokens(IClassDefinition& classDef) {
}
this->lf(2);
this->writeTag("Example");
+ this->lf(1);
+ this->writeString("// incomplete");
+ this->lf(1);
this->writeEndTag();
this->lf(2);
- this->writeEndTag("ToDo", "incomplete");
+ this->writeTag("SeeAlso");
+ this->writeSpace();
+ this->writeString("incomplete");
this->lf(2);
- this->writeEndTag();
+ switch (token.fMarkType) {
+ case MarkType::kEnum:
+ case MarkType::kEnumClass:
+ this->writeEndTag("Enum");
+ break;
+ case MarkType::kMethod:
+ this->writeEndTag("Method");
+ break;
+ case MarkType::kMember:
+ this->writeEndTag("Member");
+ continue;
+ break;
+ default:
+ SkASSERT(0);
+ }
this->lf(2);
}
}
@@ -534,6 +555,7 @@ void IncludeParser::dumpComment(const Definition& token) {
methodName.fName = string(token.fContentStart,
(int) (token.fContentEnd - token.fContentStart));
methodHasReturn = !methodParser.startsWith("void ")
+ && !methodParser.startsWith("static void ")
&& !methodParser.strnchr('~', methodParser.fEnd);
const char* paren = methodParser.strnchr('(', methodParser.fEnd);
const char* nextEnd = paren;
@@ -673,7 +695,7 @@ void IncludeParser::dumpComment(const Definition& token) {
this->nl();
}
this->lf(2);
- this->writeEndTag("Return");
+ this->writeIncompleteTag("Return");
}
}
}
@@ -829,7 +851,8 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
this->writeTag("Alias", topicName + "_Reference");
this->lf(2);
auto& classMap = fIClassMap[skClassName];
- const char* containerType = kKeyWords[(int) classMap.fKeyWord].fName;
+ SkASSERT(KeyWord::kClass == classMap.fKeyWord || KeyWord::kStruct == classMap.fKeyWord);
+ const char* containerType = KeyWord::kClass == classMap.fKeyWord ? "Class" : "Struct";
this->writeTag(containerType, skClassName);
this->lf(2);
auto& tokens = classMap.fTokens;
@@ -951,7 +974,9 @@ bool IncludeParser::dumpTokens(const string& dir, const string& skClassName) {
this->writeString(
"# ------------------------------------------------------------------------------");
this->lf(2);
- const char* containerType = kKeyWords[(int) oneClass.second.fKeyWord].fName;
+ KeyWord keyword = oneClass.second.fKeyWord;
+ SkASSERT(KeyWord::kClass == keyword || KeyWord::kStruct == keyword);
+ const char* containerType = KeyWord::kClass == keyword ? "Class" : "Struct";
this->writeTag(containerType, innerName);
this->lf(2);
this->writeTag("Code");
@@ -1389,11 +1414,39 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
auto tokenIter = child->fParent->fTokens.begin();
std::advance(tokenIter, child->fParentIndex);
tokenIter = std::prev(tokenIter);
- string nameStr(tokenIter->fStart, tokenIter->fContentEnd - tokenIter->fStart);
+ const char* nameEnd = tokenIter->fContentEnd;
+ bool addConst = false;
+ auto operatorCheck = tokenIter;
+ if ('[' == tokenIter->fStart[0] || '*' == tokenIter->fStart[0]) {
+ operatorCheck = std::prev(tokenIter);
+ }
+ if (KeyWord::kOperator == operatorCheck->fKeyWord) {
+ auto closeParen = std::next(tokenIter);
+ SkASSERT(Definition::Type::kBracket == closeParen->fType &&
+ '(' == closeParen->fContentStart[0]);
+ nameEnd = closeParen->fContentEnd + 1;
+ closeParen = std::next(closeParen);
+ if (Definition::Type::kKeyWord == closeParen->fType &&
+ KeyWord::kConst == closeParen->fKeyWord) {
+ addConst = true;
+ }
+ tokenIter = operatorCheck;
+ }
+ string nameStr(tokenIter->fStart, nameEnd - tokenIter->fStart);
+ if (addConst) {
+ nameStr += "_const";
+ }
while (tokenIter != child->fParent->fTokens.begin()) {
auto testIter = std::prev(tokenIter);
switch (testIter->fType) {
case Definition::Type::kWord:
+ if (testIter == child->fParent->fTokens.begin() &&
+ (KeyWord::kIfdef == child->fParent->fKeyWord ||
+ KeyWord::kIfndef == child->fParent->fKeyWord ||
+ KeyWord::kIf == child->fParent->fKeyWord)) {
+ std::next(tokenIter);
+ break;
+ }
goto keepGoing;
case Definition::Type::kKeyWord: {
KeyProperty keyProperty = kKeyWords[(int) testIter->fKeyWord].fProperty;
@@ -1421,6 +1474,9 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
break;
}
tokenIter->fName = nameStr;
+ if ("operator" == nameStr) {
+ SkDebugf("");
+ }
tokenIter->fMarkType = MarkType::kMethod;
tokenIter->fPrivate = string::npos != nameStr.find("::");
auto testIter = child->fParent->fTokens.begin();
@@ -1469,11 +1525,27 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
SkASSERT(child->fParentIndex > 0);
std::advance(parentIter, child->fParentIndex - 1);
Definition* methodName = &*parentIter;
- TextParser name(methodName);
- if (name.skipToEndBracket(':') && name.startsWith("::")) {
+ TextParser nameParser(methodName);
+ if (nameParser.skipToEndBracket(':') && nameParser.startsWith("::")) {
return true; // expect this is inline class definition outside of class
}
- SkASSERT(0); // code incomplete
+ string name(nameParser.fLine, nameParser.lineLength());
+ auto finder = fIFunctionMap.find(name);
+ if (fIFunctionMap.end() != finder) {
+ // create unique name
+ SkASSERT(0); // incomplete
+ }
+ auto globalFunction = &fIFunctionMap[name];
+ globalFunction->fContentStart = start;
+ globalFunction->fName = name;
+ if ("operator+" == name) {
+ SkDebugf("");
+ }
+ globalFunction->fFiddle = name;
+ globalFunction->fContentEnd = end;
+ globalFunction->fMarkType = MarkType::kMethod;
+ globalFunction->fLineCount = tokenIter->fLineCount;
+ return true;
}
markupDef->fTokens.emplace_back(MarkType::kMethod, start, end, tokenIter->fLineCount,
markupDef);
@@ -1483,6 +1555,9 @@ bool IncludeParser::parseMethod(Definition* child, Definition* markupDef) {
SkASSERT(classDef.fStart);
string uniqueName = this->uniqueName(classDef.fMethods, nameStr);
markupChild->fName = uniqueName;
+ if ("operator+" == uniqueName) {
+ SkDebugf("");
+ }
if (!this->findComments(*child, markupChild)) {
return false;
}
@@ -1574,6 +1649,7 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
case Bracket::kPound:
// special-case the #xxx xxx_DEFINED entries
switch (child->fKeyWord) {
+ case KeyWord::kIf:
case KeyWord::kIfndef:
case KeyWord::kIfdef:
if (child->boilerplateIfDef(fParent)) {
@@ -1608,7 +1684,9 @@ bool IncludeParser::parseObject(Definition* child, Definition* markupDef) {
// pick up templated function pieces when method is found
break;
case Bracket::kDebugCode:
- // todo: handle this
+ if (!this->parseObjects(child, markupDef)) {
+ return false;
+ }
break;
case Bracket::kSquare: {
// check to see if parent is operator, the only case we handle so far
@@ -1703,8 +1781,10 @@ bool IncludeParser::parseChar() {
return reportError<bool>("malformed closing comment");
}
if (Bracket::kSlashStar == this->topBracket()) {
- this->next(); // include close in bracket -- FIXME? will this skip stuff?
+ TextParser::Save save(this);
+ this->next(); // include close in bracket
this->popBracket();
+ save.restore(); // put things back so nothing is skipped
}
break;
}
@@ -1865,6 +1945,9 @@ bool IncludeParser::parseChar() {
if (fInEnum) {
break;
}
+ if (Bracket::kPound == this->topBracket()) {
+ break;
+ }
if (Bracket::kAngle == this->topBracket()) {
this->popBracket();
} else {
@@ -1882,6 +1965,10 @@ bool IncludeParser::parseChar() {
case '&':
case ',':
case ' ':
+ case '+':
+ case '=':
+ case '-':
+ case '!':
if (fInCharCommentString || fInBrace) {
break;
}
diff --git a/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp b/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp
index ff7c0e3c56f..c462826f48a 100644
--- a/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/includeWriter.cpp
@@ -8,11 +8,50 @@
#include "bookmaker.h"
void IncludeWriter::descriptionOut(const Definition* def) {
+ if ("SkPoint_length" == def->fFiddle) {
+ SkDebugf("");
+ }
const char* commentStart = def->fContentStart;
int commentLen = (int) (def->fContentEnd - commentStart);
bool breakOut = false;
+ SkDEBUGCODE(bool wroteCode = false);
for (auto prop : def->fChildren) {
switch (prop->fMarkType) {
+ case MarkType::kCode: {
+ bool literal = false;
+ bool literalOutdent = false;
+ commentLen = (int) (prop->fStart - commentStart);
+ if (commentLen > 0) {
+ SkASSERT(commentLen < 1000);
+ if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
+ this->lf(2);
+ }
+ }
+ size_t childSize = prop->fChildren.size();
+ if (childSize) {
+ SkASSERT(1 == childSize || 2 == childSize); // incomplete
+ SkASSERT(MarkType::kLiteral == prop->fChildren[0]->fMarkType);
+ SkASSERT(1 == childSize || MarkType::kOutdent == prop->fChildren[1]->fMarkType);
+ commentStart = prop->fChildren[childSize - 1]->fContentStart;
+ literal = true;
+ literalOutdent = 2 == childSize &&
+ MarkType::kOutdent == prop->fChildren[1]->fMarkType;
+ }
+ commentLen = (int) (prop->fContentEnd - commentStart);
+ SkASSERT(commentLen > 0);
+ if (literal) {
+ if (!literalOutdent) {
+ fIndent += 4;
+ }
+ this->writeBlockIndent(commentLen, commentStart);
+ this->lf(2);
+ if (!literalOutdent) {
+ fIndent -= 4;
+ }
+ commentStart = prop->fTerminator;
+ SkDEBUGCODE(wroteCode = true);
+ }
+ } break;
case MarkType::kDefinedBy:
commentStart = prop->fTerminator;
break;
@@ -48,20 +87,35 @@ void IncludeWriter::descriptionOut(const Definition* def) {
commentStart = prop->fTerminator;
commentLen = (int) (def->fContentEnd - commentStart);
break;
- case MarkType::kFormula:
+ case MarkType::kFormula: {
commentLen = prop->fStart - commentStart;
if (commentLen > 0) {
if (Wrote::kNone != this->rewriteBlock(commentLen, commentStart, Phrase::kNo)) {
- this->lfcr();
+ if (commentLen > 1 && '\n' == prop->fStart[-1] &&
+ '\n' == prop->fStart[-2]) {
+ this->lf(1);
+ } else {
+ this->writeSpace();
+ }
}
}
- this->writeBlock(prop->length(), prop->fContentStart);
+ int saveIndent = fIndent;
+ if (fIndent < fColumn + 1) {
+ fIndent = fColumn + 1;
+ }
+ this->writeBlockIndent(prop->length(), prop->fContentStart);
+ fIndent = saveIndent;
commentStart = prop->fTerminator;
commentLen = (int) (def->fContentEnd - commentStart);
- if ('\n' == commentStart[0] && '\n' == commentStart[1]) {
+ if (commentLen > 1 && '\n' == commentStart[0] && '\n' == commentStart[1]) {
this->lf(2);
+ } else {
+ SkASSERT('\n' == prop->fTerminator[0]);
+ if ('.' != prop->fTerminator[1] && !fLinefeeds) {
+ this->writeSpace();
+ }
}
- break;
+ } break;
case MarkType::kToDo:
commentLen = (int) (prop->fStart - commentStart);
if (commentLen > 0) {
@@ -105,8 +159,10 @@ void IncludeWriter::descriptionOut(const Definition* def) {
break;
}
}
- SkASSERT(commentLen > 0 && commentLen < 1500);
- this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ SkASSERT(wroteCode || (commentLen > 0 && commentLen < 1500));
+ if (commentLen > 0) {
+ this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
+ }
}
void IncludeWriter::enumHeaderOut(const RootDefinition* root,
@@ -116,6 +172,10 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root,
child.fContentStart;
this->writeBlockTrim((int) (bodyEnd - fStart), fStart); // may write nothing
this->lf(2);
+ if (fIndentNext) {
+ fIndent += 4;
+ fIndentNext = false;
+ }
fDeferComment = nullptr;
fStart = child.fContentStart;
const auto& nameDef = child.fTokens.front();
@@ -172,6 +232,9 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root,
const char* commentEnd = test->fStart;
if (!wroteHeader &&
!this->contentFree((int) (commentEnd - commentStart), commentStart)) {
+ if (fIndentNext) {
+ fIndent += 4;
+ }
this->writeCommentHeader();
this->writeString("\\enum");
if (fullName.length() > 0) {
@@ -193,9 +256,15 @@ void IncludeWriter::enumHeaderOut(const RootDefinition* root,
}
this->rewriteBlock((int) (commentEnd - commentStart), commentStart, Phrase::kNo);
if (MarkType::kAnchor == test->fMarkType) {
+ bool newLine = commentEnd - commentStart > 1 &&
+ '\n' == commentEnd[-1] && '\n' == commentEnd[-2];
commentStart = test->fContentStart;
commentEnd = test->fChildren[0]->fStart;
- this->writeSpace();
+ if (newLine) {
+ this->lf(2);
+ } else {
+ this->writeSpace();
+ }
this->rewriteBlock((int) (commentEnd - commentStart), commentStart, Phrase::kNo);
lastAnchor = true; // this->writeSpace();
}
@@ -518,12 +587,17 @@ void IncludeWriter::enumSizeItems(const Definition& child) {
// walk children and output complete method doxygen description
void IncludeWriter::methodOut(const Definition* method, const Definition& child) {
+ if (fPendingMethod) {
+ fIndent -= 4;
+ fPendingMethod = false;
+ }
fBmhMethod = method;
fMethodDef = &child;
fContinuation = nullptr;
fDeferComment = nullptr;
- if (0 == fIndent) {
- fIndent = 4;
+ if (0 == fIndent || fIndentNext) {
+ fIndent += 4;
+ fIndentNext = false;
}
this->writeCommentHeader();
fIndent += 4;
@@ -602,13 +676,17 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const
const char* blockEnd = fWroteMethod && fDeferComment ? fDeferComment->fStart - 1 :
memberStart->fStart;
this->writeBlockTrim((int) (blockEnd - blockStart), blockStart);
+ if (fIndentNext) {
+ fIndent += 4;
+ fIndentNext = false;
+ }
fWroteMethod = false;
const char* commentStart = nullptr;
ptrdiff_t commentLen = 0;
string name(child.fContentStart, (int) (child.fContentEnd - child.fContentStart));
bool isShort;
Definition* commentBlock = nullptr;
- for (auto memberDef : fStructDef->fChildren) {
+ for (auto memberDef : fBmhStructDef->fChildren) {
if (memberDef->fName.length() - name.length() == memberDef->fName.find(name)) {
commentStart = memberDef->fContentStart;
commentLen = memberDef->fContentEnd - commentStart;
@@ -668,8 +746,8 @@ Definition* IncludeWriter::structMemberOut(const Definition* memberStart, const
this->writeString("//!<");
this->writeSpace();
this->rewriteBlock(commentLen, commentStart, Phrase::kNo);
- this->lfcr();
}
+ this->lf(2);
return valueEnd;
}
@@ -784,7 +862,7 @@ void IncludeWriter::structSizeMembers(const Definition& child) {
fStructValueTab -= 1 /* ; */ ;
}
// iterate through bmh children and see which comments fit on include lines
- for (auto& member : fStructDef->fChildren) {
+ for (auto& member : fBmhStructDef->fChildren) {
if (MarkType::kMember != member->fMarkType) {
continue;
}
@@ -800,6 +878,21 @@ void IncludeWriter::structSizeMembers(const Definition& child) {
}
}
+static bool find_start(const Definition* startDef, const char* start) {
+ for (const auto& child : startDef->fTokens) {
+ if (child.fContentStart == start) {
+ return MarkType::kMethod == child.fMarkType;
+ }
+ if (child.fContentStart >= start) {
+ break;
+ }
+ if (find_start(&child, start)) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefinition* root) {
ParentPair pair = { def, prevPair };
// write bulk of original include up to class, method, enum, etc., excepting preceding comment
@@ -816,11 +909,30 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
bool inStruct = false;
bool inConstructor = false;
bool inInline = false;
+ bool eatOperator = false;
+ const Definition* requireDense = nullptr;
+ const Definition* startDef = nullptr;
for (auto& child : def->fTokens) {
+ if (KeyWord::kOperator == child.fKeyWord && method &&
+ Definition::MethodType::kOperator == method->fMethodType) {
+ eatOperator = true;
+ continue;
+ }
+ if (eatOperator) {
+ if (Bracket::kSquare == child.fBracket || Bracket::kParen == child.fBracket) {
+ continue;
+ }
+ eatOperator = false;
+ fContinuation = nullptr;
+ if (KeyWord::kConst == child.fKeyWord) {
+ continue;
+ }
+ }
if (memberEnd) {
if (memberEnd != &child) {
continue;
}
+ startDef = &child;
fStart = child.fContentStart + 1;
memberEnd = nullptr;
}
@@ -915,6 +1027,9 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
--continueEnd;
}
methodName += string(fContinuation, continueEnd - fContinuation);
+ if ("SkIPoint::operator+" == methodName) {
+ SkDebugf("");
+ }
method = root->find(methodName, RootDefinition::AllowParens::kNo);
if (!method) {
fLineCount = child.fLineCount;
@@ -958,6 +1073,7 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
continue;
}
const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
+ fAttrDeprecated ? fAttrDeprecated->fContentStart - 1 :
child.fContentStart;
// FIXME: roll end-trimming into writeBlockTrim call
while (fStart < bodyEnd && ' ' >= bodyEnd[-1]) {
@@ -967,11 +1083,18 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
if (blockSize) {
this->writeBlock(blockSize, fStart);
}
+ startDef = &child;
fStart = child.fContentStart;
methodName = root->fName + "::" + child.fName;
+ if ("SkIPoint::operator+" == methodName) {
+ SkDebugf("");
+ }
inConstructor = root->fName == child.fName;
fContinuation = child.fContentEnd;
method = root->find(methodName, RootDefinition::AllowParens::kNo);
+// if (!method) {
+// method = root->find(methodName + "()", RootDefinition::AllowParens::kNo);
+// }
if (!method) {
continue;
}
@@ -981,13 +1104,25 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
this->methodOut(method, child);
if (fAttrDeprecated) {
+ startDef = fAttrDeprecated;
fStart = fAttrDeprecated->fContentStart;
fAttrDeprecated = nullptr;
}
continue;
}
if (Definition::Type::kKeyWord == child.fType) {
- const Definition* structDef = nullptr;
+ if (fIndentNext) {
+ // too soon
+#if 0 // makes struct Lattice indent when it oughtn't
+ if (KeyWord::kEnum == child.fKeyWord) {
+ fIndent += 4;
+ }
+ if (KeyWord::kPublic != child.fKeyWord) {
+ fIndentNext = false;
+ }
+#endif
+ }
+ const Definition* cIncludeStructDef = nullptr;
switch (child.fKeyWord) {
case KeyWord::kStruct:
case KeyWord::kClass:
@@ -1002,20 +1137,51 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
}
}
if (fInStruct) {
+ // try child; root+child; root->parent+child; etc.
+ int trial = 0;
+ const RootDefinition* search = root;
+ const Definition* parent = search->fParent;
+ do {
+ string name;
+ if (0 == trial) {
+ name = child.fName;
+ } else if (1 == trial) {
+ name = root->fName + "::" + child.fName;
+ } else {
+ SkASSERT(parent);
+ name = parent->fName + "::" + child.fName;
+ search = parent->asRoot();
+ parent = search->fParent;
+ }
+ fBmhStructDef = search->find(name, RootDefinition::AllowParens::kNo);
+ } while (!fBmhStructDef && ++trial);
+ root = const_cast<RootDefinition*>(fBmhStructDef->asRoot());
+ SkASSERT(root);
fIndent += 4;
- fStructDef = root->find(child.fName, RootDefinition::AllowParens::kNo);
- if (nullptr == structDef) {
- fStructDef = root->find(root->fName + "::" + child.fName,
- RootDefinition::AllowParens::kNo);
- }
this->structSizeMembers(child);
fIndent -= 4;
+ SkASSERT(!fIndentNext);
+ fIndentNext = true;
}
if (child.fChildren.size() > 0) {
const char* bodyEnd = fDeferComment ? fDeferComment->fContentStart - 1 :
child.fContentStart;
this->writeBlockTrim((int) (bodyEnd - fStart), fStart);
- fStart = child.fContentStart;
+ if (fPendingMethod) {
+ fIndent -= 4;
+ fPendingMethod = false;
+ }
+ startDef = requireDense ? requireDense : &child;
+ fStart = requireDense ? requireDense->fContentStart : child.fContentStart;
+ requireDense = nullptr;
+ if (!fInStruct && child.fName != root->fName) {
+ root = &fBmhParser->fClassMap[child.fName];
+ fRootTopic = root->fParent;
+ SkASSERT(!root->fVisited);
+ root->clearVisited();
+ fIndent = 0;
+ fBmhStructDef = root;
+ }
if (child.fName == root->fName) {
if (Definition* parent = root->fParent) {
if (MarkType::kTopic == parent->fMarkType ||
@@ -1030,36 +1196,43 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
SkASSERT(0); // incomplete
}
} else {
- structDef = root->find(child.fName, RootDefinition::AllowParens::kNo);
- if (nullptr == structDef) {
- structDef = root->find(root->fName + "::" + child.fName,
+ SkASSERT(fInStruct);
+ #if 0
+ fBmhStructDef = root->find(child.fName, RootDefinition::AllowParens::kNo);
+ if (nullptr == fBmhStructDef) {
+ fBmhStructDef = root->find(root->fName + "::" + child.fName,
RootDefinition::AllowParens::kNo);
}
- if (!structDef) {
+ if (!fBmhStructDef) {
this->lf(2);
fIndent = 0;
this->writeBlock((int) (fStart - bodyEnd), bodyEnd);
this->lfcr();
continue;
}
+ #endif
Definition* codeBlock = nullptr;
- SkDEBUGCODE(Definition* nextBlock = nullptr);
- for (auto test : structDef->fChildren) {
+ Definition* nextBlock = nullptr;
+ for (auto test : fBmhStructDef->fChildren) {
if (MarkType::kCode == test->fMarkType) {
SkASSERT(!codeBlock); // FIXME: check enum for correct order earlier
codeBlock = test;
continue;
}
if (codeBlock) {
- SkDEBUGCODE(nextBlock = test);
+ nextBlock = test;
break;
}
}
// FIXME: trigger error earlier if inner #Struct or #Class is missing #Code
SkASSERT(nextBlock); // FIXME: check enum for correct order earlier
- const char* commentStart = structDef->fContentStart;
- const char* commentEnd = codeBlock->fStart;
- this->structOut(root, *structDef, commentStart, commentEnd);
+ const char* commentStart = codeBlock->fTerminator;
+ const char* commentEnd = nextBlock->fStart;
+ if (fIndentNext) {
+// fIndent += 4;
+ }
+ fIndentNext = true;
+ this->structOut(root, *fBmhStructDef, commentStart, commentEnd);
}
fDeferComment = nullptr;
} else {
@@ -1096,17 +1269,21 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
case KeyWord::kSK_API:
case KeyWord::kTypedef:
break;
+ case KeyWord::kSK_BEGIN_REQUIRE_DENSE:
+ requireDense = &child;
+ break;
default:
SkASSERT(0);
}
- if (structDef) {
+ if (cIncludeStructDef) {
TextParser structName(&child);
SkAssertResult(structName.skipToEndBracket('{'));
+ startDef = &child;
fStart = structName.fChar + 1;
this->writeBlock((int) (fStart - child.fStart), child.fStart);
this->lf(2);
fIndent += 4;
- if (!this->populate(&child, &pair, const_cast<Definition*>(structDef)->asRoot())) {
+ if (!this->populate(&child, &pair, const_cast<Definition*>(cIncludeStructDef)->asRoot())) {
return false;
}
// output any remaining definitions at current indent level
@@ -1126,8 +1303,28 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
if (!this->populate(child.fChildren[0], &pair, root)) {
return false;
}
- } else if (!this->populate(&child, &pair, root)) {
- return false;
+ } else {
+ if (!this->populate(&child, &pair, root)) {
+ return false;
+ }
+ if (KeyWord::kClass == child.fKeyWord || KeyWord::kStruct == child.fKeyWord) {
+ fStructMemberTab = 0;
+ if (fInStruct) {
+ fInStruct = false;
+ do {
+ SkASSERT(root);
+ root = const_cast<RootDefinition*>(root->fParent->asRoot());
+ } while (MarkType::kTopic == root->fMarkType ||
+ MarkType::kSubtopic == root->fMarkType);
+ SkASSERT(MarkType::kStruct == root->fMarkType ||
+ MarkType::kClass == root->fMarkType);
+ fPendingMethod = false;
+ if (startDef) {
+ fPendingMethod = find_start(startDef, fStart);
+ }
+ fOutdentNext = !fPendingMethod;
+ }
+ }
}
}
continue;
@@ -1140,17 +1337,25 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
this->enumMembersOut(root, child);
this->writeString("};");
this->lf(2);
+ startDef = child.fParent;
fStart = child.fParent->fContentEnd;
SkASSERT(';' == fStart[0]);
++fStart;
fDeferComment = nullptr;
fInEnum = false;
+ if (fIndentNext) {
+// fIndent -= 4;
+ fIndentNext = false;
+ }
continue;
}
if (fAttrDeprecated) {
continue;
}
fDeferComment = nullptr;
+ if (KeyWord::kClass == def->fKeyWord || KeyWord::kStruct == def->fKeyWord) {
+ fIndentNext = true;
+ }
if (!this->populate(&child, &pair, root)) {
return false;
}
@@ -1162,13 +1367,17 @@ bool IncludeWriter::populate(Definition* def, ParentPair* prevPair, RootDefiniti
auto iter = def->fTokens.begin();
std::advance(iter, child.fParentIndex - 1);
memberStart = &*iter;
- if (!fStructDef) {
+ if (!fStructMemberTab) {
SkASSERT(KeyWord::kStruct == def->fParent->fKeyWord);
- fStructDef = def->fParent;
- this->structSizeMembers(*fStructDef);
+ fIndent += 4;
+ this->structSizeMembers(*def->fParent);
+ fIndent -= 4;
+// SkASSERT(!fIndentNext);
+ fIndentNext = true;
}
}
memberEnd = this->structMemberOut(memberStart, child);
+ startDef = &child;
fStart = child.fContentEnd + 1;
fDeferComment = nullptr;
}
@@ -1322,8 +1531,8 @@ string IncludeWriter::resolveRef(const char* start, const char* end, bool first,
rootDefIter = fBmhParser->fTopicMap.find(prefixedName);
if (fBmhParser->fTopicMap.end() != rootDefIter) {
rootDef = rootDefIter->second;
- } else if (fStructDef) {
- string localPrefix = fStructDef->fFiddle + '_' + undername;
+ } else if (fBmhStructDef) {
+ string localPrefix = fBmhStructDef->fFiddle + '_' + undername;
rootDefIter = fBmhParser->fTopicMap.find(localPrefix);
if (fBmhParser->fTopicMap.end() != rootDefIter) {
rootDef = rootDefIter->second;
@@ -1500,6 +1709,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
if (lastPrintable >= lastWrite) {
if (' ' == data[lastWrite]) {
this->writeSpace();
+ lastWrite++;
}
this->writeBlock(lastPrintable - lastWrite + 1, &data[lastWrite]);
}
@@ -1648,7 +1858,7 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
break;
case Word::kCap:
case Word::kFirst:
- if (!isupper(last)) {
+ if (!isupper(last) && '~' != last) {
word = Word::kMixed;
}
break;
@@ -1697,6 +1907,14 @@ IncludeWriter::Wrote IncludeWriter::rewriteBlock(int size, const char* data, Phr
hasIndirection |= embeddedIndirection;
hasSymbol |= embeddedSymbol;
break;
+ case '~':
+ SkASSERT(Word::kStart == word);
+ word = PunctuationState::kStart == punctuation ? Word::kFirst : Word::kCap;
+ start = run;
+ hasUpper = true;
+ hasIndirection |= embeddedIndirection;
+ hasSymbol |= embeddedSymbol;
+ break;
default:
SkASSERT(0);
}
diff --git a/chromium/third_party/skia/tools/bookmaker/mdOut.cpp b/chromium/third_party/skia/tools/bookmaker/mdOut.cpp
index 242d667736d..6b082ad1de4 100644
--- a/chromium/third_party/skia/tools/bookmaker/mdOut.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/mdOut.cpp
@@ -62,7 +62,10 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
lineStart = false;
} else {
leadingSpaces = string(base, wordStart - base);
- }
+ }
+ if (!strncmp("SkPoint::operator-()", start, 20)) {
+ SkDebugf("");
+ }
t.skipToMethodEnd();
if (base == t.fChar) {
break;
@@ -74,6 +77,9 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
continue;
}
ref = string(start, t.fChar - start);
+ if (412 == t.fLineCount) {
+ SkDebugf("");
+ }
if (const Definition* def = this->isDefined(t, ref,
BmhParser::Resolvable::kOut != resolvable)) {
SkASSERT(def->fFiddle.length());
@@ -105,7 +111,8 @@ string MdOut::addReferences(const char* refStart, const char* refEnd,
return result;
}
if (!foundMatch) {
- if (!(def = this->isDefined(t, fullRef, true))) {
+ if (!(def = this->isDefined(t, fullRef,
+ BmhParser::Resolvable::kOut != resolvable))) {
if (!result.size()) {
t.reportError("missing method");
}
@@ -324,7 +331,7 @@ bool MdOut::buildRefFromFile(const char* name, const char* outDir) {
bool MdOut::checkParamReturnBody(const Definition* def) const {
TextParser paramBody(def);
const char* descriptionStart = paramBody.fChar;
- if (!islower(descriptionStart[0])) {
+ if (!islower(descriptionStart[0]) && !isdigit(descriptionStart[0])) {
paramBody.skipToNonAlphaNum();
string ref = string(descriptionStart, paramBody.fChar - descriptionStart);
if (!this->isDefined(paramBody, ref, true)) {
@@ -349,7 +356,7 @@ void MdOut::childrenOut(const Definition* def, const char* start) {
} else if (MarkType::kEnumClass == def->fMarkType) {
fEnumClass = def;
}
- BmhParser::Resolvable resolvable = this->resolvable(def->fMarkType);
+ BmhParser::Resolvable resolvable = this->resolvable(def);
for (auto& child : def->fChildren) {
end = child->fStart;
if (BmhParser::Resolvable::kNo != resolvable) {
@@ -640,7 +647,7 @@ void MdOut::markTypeOut(Definition* def) {
case MarkType::kCode:
this->lfAlways(2);
fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;"
- "width: 44em; background-color: #f0f0f0\">");
+ "width: 62.5em; background-color: #f0f0f0\">");
this->lf(1);
break;
case MarkType::kColumn:
@@ -705,17 +712,34 @@ void MdOut::markTypeOut(Definition* def) {
fprintf(fOut, "Example\n"
"\n");
fHasFiddle = true;
+ bool showGpu = false;
+ bool gpuAndCpu = false;
const Definition* platform = def->hasChild(MarkType::kPlatform);
if (platform) {
TextParser platParse(platform);
fHasFiddle = !platParse.strnstr("!fiddle", platParse.fEnd);
+ showGpu = platParse.strnstr("gpu", platParse.fEnd);
+ if (showGpu) {
+ gpuAndCpu = platParse.strnstr("cpu", platParse.fEnd);
+ }
}
if (fHasFiddle) {
- fprintf(fOut, "<div><fiddle-embed name=\"%s\">", def->fHash.c_str());
+ fprintf(fOut, "<div><fiddle-embed name=\"%s\"", def->fHash.c_str());
+ if (showGpu) {
+ fprintf(fOut, "gpu=\"true\"");
+ if (gpuAndCpu) {
+ fprintf(fOut, "cpu=\"true\"");
+ }
+ }
+ fprintf(fOut, ">");
} else {
- fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;"
- "width: 44em; background-color: #f0f0f0\">");
- this->lf(1);
+ fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em; font-size: 13px"
+ " width: 62.5em; background-color: #f0f0f0\">");
+ this->lfAlways(1);
+ if (def->fWrapper.length() > 0) {
+ fprintf(fOut, "%s", def->fWrapper.c_str());
+ }
+ fRespectLeadingSpace = true;
}
} break;
case MarkType::kExperimental:
@@ -742,6 +766,8 @@ void MdOut::markTypeOut(Definition* def) {
fprintf(fOut, "<table>");
this->lf(1);
break;
+ case MarkType::kLiteral:
+ break;
case MarkType::kMarkChar:
fBmhParser.fMC = def->fContentStart[0];
break;
@@ -768,11 +794,11 @@ void MdOut::markTypeOut(Definition* def) {
}
// TODO: put in css spec that we can define somewhere else (if markup supports that)
- // TODO: 50em below should match limt = 80 in formatFunction()
+ // TODO: 50em below should match limit = 80 in formatFunction()
this->writePending();
string preformattedStr = preformat(formattedStr);
fprintf(fOut, "<pre style=\"padding: 1em 1em 1em 1em;"
- "width: 50em; background-color: #f0f0f0\">\n"
+ "width: 62.5em; background-color: #f0f0f0\">\n"
"%s\n"
"</pre>", preformattedStr.c_str());
this->lf(2);
@@ -781,6 +807,8 @@ void MdOut::markTypeOut(Definition* def) {
} break;
case MarkType::kNoExample:
break;
+ case MarkType::kOutdent:
+ break;
case MarkType::kParam: {
if (TableState::kNone == fTableState) {
this->mdHeaderOut(3);
@@ -932,9 +960,15 @@ void MdOut::markTypeOut(Definition* def) {
if (fHasFiddle) {
fprintf(fOut, "</fiddle-embed></div>");
} else {
+ this->lfAlways(1);
+ if (def->fWrapper.length() > 0) {
+ fprintf(fOut, "}");
+ this->lfAlways(1);
+ }
fprintf(fOut, "</pre>");
}
this->lf(2);
+ fRespectLeadingSpace = false;
break;
case MarkType::kList:
fInList = false;
@@ -1004,6 +1038,24 @@ void MdOut::mdHeaderOutLF(int depth, int lf) {
}
void MdOut::resolveOut(const char* start, const char* end, BmhParser::Resolvable resolvable) {
+ if ((BmhParser::Resolvable::kLiteral == resolvable || fRespectLeadingSpace) && end > start) {
+ while ('\n' == *start) {
+ ++start;
+ }
+ const char* spaceStart = start;
+ while (' ' == *start) {
+ ++start;
+ }
+ if (start > spaceStart) {
+ fIndent = start - spaceStart;
+ }
+ this->writeBlockTrim(end - start, start);
+ if ('\n' == end[-1]) {
+ this->lf(1);
+ }
+ fIndent = 0;
+ return;
+ }
// FIXME: this needs the markdown character present when the def was defined,
// not the last markdown character the parser would have seen...
while (fBmhParser.fMC == end[-1]) {
diff --git a/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp b/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp
index cb55bcb640b..79503a66b31 100644
--- a/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/parserCommon.cpp
@@ -7,8 +7,41 @@
#include "bookmaker.h"
+#include "SkOSFile.h"
+#include "SkOSPath.h"
+
+static void debug_out(int len, const char* data) {
+ // convenient place to intercept arbitrary output
+ SkDebugf("%.*s", len, data);
+}
+
+bool ParserCommon::parseFile(const char* fileOrPath, const char* suffix) {
+// this->reset();
+ if (!sk_isdir(fileOrPath)) {
+ if (!this->parseFromFile(fileOrPath)) {
+ SkDebugf("failed to parse %s\n", fileOrPath);
+ return false;
+ }
+ } else {
+ SkOSFile::Iter it(fileOrPath, suffix);
+ for (SkString file; it.next(&file); ) {
+ SkString p = SkOSPath::Join(fileOrPath, file.c_str());
+ const char* hunk = p.c_str();
+ if (!SkStrEndsWith(hunk, suffix)) {
+ continue;
+ }
+ if (!this->parseFromFile(hunk)) {
+ SkDebugf("failed to parse %s\n", hunk);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
bool ParserCommon::parseSetup(const char* path) {
- this->reset();
+// this->reset();
sk_sp<SkData> data = SkData::MakeFromFileName(path);
if (nullptr == data.get()) {
SkDebugf("%s missing\n", path);
@@ -49,3 +82,131 @@ bool ParserCommon::parseSetup(const char* path) {
fLineCount = 1;
return true;
}
+
+void ParserCommon::writeBlockIndent(int size, const char* data) {
+ while (size && ' ' >= data[size - 1]) {
+ --size;
+ }
+ bool newLine = false;
+ while (size) {
+ while (size && ' ' > data[0]) {
+ ++data;
+ --size;
+ }
+ if (!size) {
+ return;
+ }
+ if (newLine) {
+ this->lf(1);
+ }
+ TextParser parser(fFileName, data, data + size, fLineCount);
+ const char* lineEnd = parser.strnchr('\n', data + size);
+ int len = lineEnd ? (int) (lineEnd - data) : size;
+ this->writePending();
+ this->indentToColumn(fIndent);
+ if (fDebugOut) {
+ debug_out(len, data);
+ }
+ fprintf(fOut, "%.*s", len, data);
+ size -= len;
+ data += len;
+ newLine = true;
+ }
+}
+
+bool ParserCommon::writeBlockTrim(int size, const char* data) {
+ if (fOutdentNext) {
+ fIndent -= 4;
+ fOutdentNext = false;
+ }
+ while (size && ' ' >= data[0]) {
+ ++data;
+ --size;
+ }
+ while (size && ' ' >= data[size - 1]) {
+ --size;
+ }
+ if (size <= 0) {
+ fLastChar = '\0';
+ return false;
+ }
+ SkASSERT(size < 16000);
+ if (size > 3 && !strncmp("#end", data, 4)) {
+ fMaxLF = 1;
+ }
+ if (this->leadingPunctuation(data, (size_t) size)) {
+ fPendingSpace = 0;
+ }
+ this->writePending();
+ if (fDebugOut) {
+ debug_out(size, data);
+ }
+ fprintf(fOut, "%.*s", size, data);
+ int added = 0;
+ fLastChar = data[size - 1];
+ while (size > 0 && '\n' != data[--size]) {
+ ++added;
+ }
+ fColumn = size ? added : fColumn + added;
+ fSpaces = 0;
+ fLinefeeds = 0;
+ fMaxLF = added > 2 && !strncmp("#if", &data[size + (size > 0)], 3) ? 1 : 2;
+ if (fOutdentNext) {
+ fIndent -= 4;
+ fOutdentNext = false;
+ }
+ return true;
+}
+
+void ParserCommon::writePending() {
+ fPendingLF = SkTMin(fPendingLF, fMaxLF);
+ bool wroteLF = false;
+ while (fLinefeeds < fPendingLF) {
+ if (fDebugOut) {
+ SkDebugf("\n");
+ }
+ fprintf(fOut, "\n");
+ ++fLinefeeds;
+ wroteLF = true;
+ }
+ fPendingLF = 0;
+ if (wroteLF) {
+ SkASSERT(0 == fColumn);
+ SkASSERT(fIndent >= fSpaces);
+ if (fDebugOut) {
+ SkDebugf("%*s", fIndent - fSpaces, "");
+ }
+ fprintf(fOut, "%*s", fIndent - fSpaces, "");
+ fColumn = fIndent;
+ fSpaces = fIndent;
+ }
+ for (int index = 0; index < fPendingSpace; ++index) {
+ if (fDebugOut) {
+ SkDebugf(" ");
+ }
+ fprintf(fOut, " ");
+ ++fColumn;
+ }
+ fPendingSpace = 0;
+}
+
+void ParserCommon::writeString(const char* str) {
+ const size_t len = strlen(str);
+ SkASSERT(len > 0);
+ SkASSERT(' ' < str[0]);
+ fLastChar = str[len - 1];
+ SkASSERT(' ' < fLastChar);
+ SkASSERT(!strchr(str, '\n'));
+ if (this->leadingPunctuation(str, strlen(str))) {
+ fPendingSpace = 0;
+ }
+ this->writePending();
+ if (fDebugOut) {
+ debug_out((int) strlen(str), str);
+ }
+ fprintf(fOut, "%s", str);
+ fColumn += len;
+ fSpaces = 0;
+ fLinefeeds = 0;
+ fMaxLF = 2;
+}
diff --git a/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp b/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp
index 3a32f37bc48..6f50cb3bb52 100644
--- a/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp
+++ b/chromium/third_party/skia/tools/bookmaker/spellCheck.cpp
@@ -202,6 +202,8 @@ bool SpellCheck::check(Definition* def) {
break;
case MarkType::kList:
break;
+ case MarkType::kLiteral:
+ break;
case MarkType::kMarkChar:
break;
case MarkType::kMember:
@@ -212,7 +214,7 @@ bool SpellCheck::check(Definition* def) {
method_name += "()";
}
string formattedStr = def->formatFunction();
- if (!def->isClone()) {
+ if (!def->isClone() && Definition::MethodType::kOperator != def->fMethodType) {
this->wordCheck(method_name);
}
fTableState = TableState::kNone;
@@ -220,6 +222,8 @@ bool SpellCheck::check(Definition* def) {
} break;
case MarkType::kNoExample:
break;
+ case MarkType::kOutdent:
+ break;
case MarkType::kParam: {
if (TableState::kNone == fTableState) {
fTableState = TableState::kRow;
@@ -490,6 +494,7 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) {
if (report.contains("all")) {
int column = 0;
char lastInitial = 'a';
+ int count = 0;
for (auto iter : elems) {
if (string::npos != iter.second.fFile.find("undocumented.bmh")) {
continue;
@@ -521,8 +526,9 @@ void SpellCheck::report(SkCommandLineFlags::StringArray report) {
}
SkDebugf("%s ", check.c_str());
column += check.length();
+ ++count;
}
- SkDebugf("\n\n");
+ SkDebugf("\n\ncount = %d\n", count);
return;
}
int index = 0;
@@ -607,7 +613,9 @@ void SpellCheck::wordCheck(const string& str) {
std::istringstream ss(str);
string token;
while (std::getline(ss, token, '_')) {
- this->wordCheck(token);
+ if (token.length()) {
+ this->wordCheck(token);
+ }
}
return;
}
diff --git a/chromium/third_party/skia/tools/calmbench/ab.py b/chromium/third_party/skia/tools/calmbench/ab.py
index 2ffb9e3ec36..b5b5c8d5e10 100644
--- a/chromium/third_party/skia/tools/calmbench/ab.py
+++ b/chromium/third_party/skia/tools/calmbench/ab.py
@@ -74,6 +74,15 @@ def parse_args():
parser.add_argument('noinit', type=str, help=("whether to skip running B"
" ('true' or 'false')"))
+ parser.add_argument('--concise', dest='concise', action="store_true",
+ help="If set, no verbose thread info will be printed.")
+ parser.set_defaults(concise=False)
+
+ # Additional args for bots
+ BHELP = "bot specific options"
+ parser.add_argument('--githash', type=str, default="", help=BHELP)
+ parser.add_argument('--keys', type=str, default=[], nargs='+', help=BHELP)
+
args = parser.parse_args()
args.skip_b = args.skip_b == "true"
args.noinit = args.noinit == "true"
@@ -112,7 +121,8 @@ def append_times_from_file(args, name, filename):
class ThreadRunner:
"""Simplest and stupidiest threaded executer."""
- def __init__(self):
+ def __init__(self, args):
+ self.concise = args.concise
self.threads = []
def add(self, args, fn):
@@ -138,12 +148,16 @@ class ThreadRunner:
time.sleep(0.5)
i += 1
- ts = Thread(target = spin);
- ts.start()
+ if not self.concise:
+ ts = Thread(target = spin);
+ ts.start()
+
for t in self.threads:
t.join()
self.threads = []
- ts.join()
+
+ if not self.concise:
+ ts.join()
def split_arg(arg):
@@ -183,7 +197,7 @@ def run(args, threadRunner, name, nano, arg, i):
def init_run(args):
- threadRunner = ThreadRunner()
+ threadRunner = ThreadRunner(args)
for i in range(1, max(args.repeat, args.threads / 2) + 1):
run(args, threadRunner, args.a, args.nano_a, args.arg_a, i)
run(args, threadRunner, args.b, args.nano_b, args.arg_b, i)
@@ -243,6 +257,13 @@ def format_r(r):
return ('%6.2f' % percentage(r)) + "%"
+def normalize_r(r):
+ if r > 1.0:
+ return r - 1.0
+ else:
+ return 1.0 - 1/r
+
+
def test():
args = parse_args()
@@ -261,7 +282,7 @@ def test():
break
print "Number of suspects at iteration %d: %d" % (it, len(suspects))
- threadRunner = ThreadRunner()
+ threadRunner = ThreadRunner(args)
for j in range(1, max(1, args.threads / 2) + 1):
run(args, threadRunner, args.a, args.nano_a,
args.arg_a + suspects_arg(suspects), -j)
@@ -287,10 +308,26 @@ def test():
(format_r(r), suspect)
with open("%s/bench_%s_%s.json" % (args.outdir, args.a, args.b), 'w') as f:
- f.write(json.dumps(map(
- lambda bench: {bench: regression(bench)},
- suspects
- )))
+ results = {}
+ for bench in timesA:
+ r = regression(bench) if bench in suspects else 1.0
+ results[bench] = {
+ args.config: {
+ "signed_regression": normalize_r(r),
+ "lower_quantile_ms": get_lower_upper(timesA[bench])[0] * 1e-6,
+ "upper_quantile_ms": get_lower_upper(timesA[bench])[1] * 1e-6
+ }
+ }
+
+ output = {"results": results}
+ if args.githash:
+ output["gitHash"] = args.githash
+ if args.keys:
+ keys = {}
+ for i in range(len(args.keys) / 2):
+ keys[args.keys[i * 2]] = args.keys[i * 2 + 1]
+ output["key"] = keys
+ f.write(json.dumps(output, indent=4))
print ("\033[36mJSON results available in %s\033[0m" % f.name)
with open("%s/bench_%s_%s.csv" % (args.outdir, args.a, args.b), 'w') as out:
diff --git a/chromium/third_party/skia/tools/calmbench/calmbench.py b/chromium/third_party/skia/tools/calmbench/calmbench.py
index 4d1319de1a0..b786b5f346d 100644
--- a/chromium/third_party/skia/tools/calmbench/calmbench.py
+++ b/chromium/third_party/skia/tools/calmbench/calmbench.py
@@ -74,6 +74,9 @@ def parse_args():
'(i.e., reuse previous baseline measurements)')
noinit_help = (
'whether to skip initial nanobench runs (default: %(default)s)')
+ branch_help = (
+ "the test branch to benchmark; if it's 'modified', we'll benchmark the "
+ "current modified code against 'git stash'.")
definitions = [
# argname, type, default value, help
@@ -85,22 +88,30 @@ def parse_args():
['--baseline', str, 'master', baseline_help],
['--basearg', str, '', basearg_help],
['--reps', int, 2, reps_help],
- ['--threads', int, default_threads, threads_help]
+ ['--threads', int, default_threads, threads_help],
]
for d in definitions:
parser.add_argument(d[0], type=d[1], default=d[2], help=d[3])
- parser.add_argument('branch', type=str, help="the test branch to benchmark")
+ parser.add_argument('branch', type=str, help=branch_help)
parser.add_argument('--no-compile', dest='no_compile', action="store_true",
help=no_compile_help)
parser.add_argument('--skip-base', dest='skipbase', action="store_true",
help=skip_base_help)
parser.add_argument('--noinit', dest='noinit', action="store_true",
help=noinit_help)
+ parser.add_argument('--concise', dest='concise', action="store_true",
+ help="If set, no verbose thread info will be printed.")
parser.set_defaults(no_compile=False);
parser.set_defaults(skipbase=False);
parser.set_defaults(noinit=False);
+ parser.set_defaults(concise=False);
+
+ # Additional args for bots
+ BHELP = "bot specific options"
+ parser.add_argument('--githash', type=str, help=BHELP)
+ parser.add_argument('--keys', type=str, default=[], nargs='+', help=BHELP)
args = parser.parse_args()
if not args.basearg:
@@ -116,7 +127,6 @@ def nano_path(args, branch):
def compile_branch(args, branch):
print "Compiling branch %s" % args.branch
- os.chdir(args.skiadir)
commands = [
['git', 'checkout', branch],
['ninja', '-C', args.ninjadir, 'nanobench'],
@@ -126,9 +136,33 @@ def compile_branch(args, branch):
subprocess.check_call(command, cwd=args.skiadir)
+def compile_modified(args):
+ print "Compiling modified code"
+ subprocess.check_call(
+ ['ninja', '-C', args.ninjadir, 'nanobench'], cwd=args.skiadir)
+ subprocess.check_call(
+ ['cp', args.ninjadir + '/nanobench', nano_path(args, args.branch)],
+ cwd=args.skiadir)
+
+ print "Compiling stashed code"
+ stash_output = subprocess.check_output(['git', 'stash'], cwd=args.skiadir)
+ if 'No local changes to save' in stash_output:
+ subprocess.check_call(['git', 'reset', 'HEAD^', '--soft'])
+ subprocess.check_call(['git', 'stash'])
+
+ subprocess.check_call(
+ ['ninja', '-C', args.ninjadir, 'nanobench'], cwd=args.skiadir)
+ subprocess.check_call(
+ ['cp', args.ninjadir + '/nanobench', nano_path(args, args.baseline)],
+ cwd=args.skiadir)
+ subprocess.check_call(['git', 'stash', 'pop'], cwd=args.skiadir)
+
def compile_nanobench(args):
- compile_branch(args, args.branch)
- compile_branch(args, args.baseline)
+ if args.branch == 'modified':
+ compile_modified(args)
+ else:
+ compile_branch(args, args.branch)
+ compile_branch(args, args.baseline)
def main():
@@ -160,6 +194,14 @@ def main():
"true" if args.noinit else "false"
]
+ if args.githash:
+ command += ['--githash', args.githash]
+ if args.keys:
+ command += (['--keys'] + args.keys)
+
+ if args.concise:
+ command.append("--concise")
+
p = subprocess.Popen(command, cwd=args.skiadir)
try:
p.wait()
diff --git a/chromium/third_party/skia/tools/colorspaceinfo.cpp b/chromium/third_party/skia/tools/colorspaceinfo.cpp
index 3e09a9aeebe..0002e961cf7 100644
--- a/chromium/third_party/skia/tools/colorspaceinfo.cpp
+++ b/chromium/third_party/skia/tools/colorspaceinfo.cpp
@@ -565,13 +565,13 @@ int main(int argc, char** argv) {
SkColorSpace_A2B* a2b = static_cast<SkColorSpace_A2B*>(colorSpace.get());
SkDebugf("Conversion type: ");
switch (a2b->iccType()) {
- case SkColorSpace_Base::kRGB_ICCTypeFlag:
+ case SkColorSpace::kRGB_Type:
SkDebugf("RGB");
break;
- case SkColorSpace_Base::kCMYK_ICCTypeFlag:
+ case SkColorSpace::kCMYK_Type:
SkDebugf("CMYK");
break;
- case SkColorSpace_Base::kGray_ICCTypeFlag:
+ case SkColorSpace::kGray_Type:
SkDebugf("Gray");
break;
default:
diff --git a/chromium/third_party/skia/tools/create_flutter_test_images.cpp b/chromium/third_party/skia/tools/create_flutter_test_images.cpp
index 69a0d112a32..2fa39f6c759 100644
--- a/chromium/third_party/skia/tools/create_flutter_test_images.cpp
+++ b/chromium/third_party/skia/tools/create_flutter_test_images.cpp
@@ -15,19 +15,7 @@
* Create a color space that swaps the red, green, and blue channels.
*/
static sk_sp<SkColorSpace> gbr_color_space() {
- float gbr[9];
- gbr[0] = gSRGB_toXYZD50[1];
- gbr[1] = gSRGB_toXYZD50[2];
- gbr[2] = gSRGB_toXYZD50[0];
- gbr[3] = gSRGB_toXYZD50[4];
- gbr[4] = gSRGB_toXYZD50[5];
- gbr[5] = gSRGB_toXYZD50[3];
- gbr[6] = gSRGB_toXYZD50[7];
- gbr[7] = gSRGB_toXYZD50[8];
- gbr[8] = gSRGB_toXYZD50[6];
- SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
- toXYZD50.set3x3RowMajorf(gbr);
- return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, toXYZD50);
+ return as_CSB(SkColorSpace::MakeSRGB())->makeColorSpin();
}
/**
diff --git a/chromium/third_party/skia/tools/debugger/SkDebugCanvas.h b/chromium/third_party/skia/tools/debugger/SkDebugCanvas.h
index 72d65d7da7e..634d5b416df 100644
--- a/chromium/third_party/skia/tools/debugger/SkDebugCanvas.h
+++ b/chromium/third_party/skia/tools/debugger/SkDebugCanvas.h
@@ -165,25 +165,6 @@ public:
Json::Value toJSONOpList(int n, SkCanvas*);
- ////////////////////////////////////////////////////////////////////////////////
- // Inherited from SkCanvas
- ////////////////////////////////////////////////////////////////////////////////
-
- static const int kVizImageHeight = 256;
- static const int kVizImageWidth = 256;
-
- bool isClipEmpty() const override { return false; }
-
- bool isClipRect() const override { return true; }
-
- SkRect onGetLocalClipBounds() const override {
- return SkRect::MakeIWH(this->imageInfo().width(), this->imageInfo().height());
- }
-
- SkIRect onGetDeviceClipBounds() const override {
- return SkIRect::MakeWH(this->imageInfo().width(), this->imageInfo().height());
- }
-
void detachCommands(SkTDArray<SkDrawCommand*>* dst) {
fCommandVector.swap(*dst);
}
diff --git a/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp b/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp
index 4b075dd2f24..bdabc8aea56 100644
--- a/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp
+++ b/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.cpp
@@ -134,12 +134,6 @@ size_t SkJsonWriteBuffer::writeStream(SkStream* stream, size_t length) {
return 0;
}
-void SkJsonWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
- Json::Value jsonBitmap;
- SkDrawCommand::flatten(bitmap, &jsonBitmap, *fUrlDataManager);
- this->append("bitmap", jsonBitmap);
-}
-
void SkJsonWriteBuffer::writeImage(const SkImage* image) {
Json::Value jsonImage;
SkDrawCommand::flatten(*image, &jsonImage, *fUrlDataManager);
diff --git a/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.h b/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.h
index a0cf4e720bf..c1a72313e0c 100644
--- a/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.h
+++ b/chromium/third_party/skia/tools/debugger/SkJsonWriteBuffer.h
@@ -45,7 +45,6 @@ public:
void writeRegion(const SkRegion& region) override;
void writePath(const SkPath& path) override;
size_t writeStream(SkStream* stream, size_t length) override;
- void writeBitmap(const SkBitmap& bitmap) override;
void writeImage(const SkImage*) override;
void writeTypeface(SkTypeface* typeface) override;
void writePaint(const SkPaint& paint) override;
diff --git a/chromium/third_party/skia/tools/dump_record.cpp b/chromium/third_party/skia/tools/dump_record.cpp
index 24017bd6c9e..783c378f447 100644
--- a/chromium/third_party/skia/tools/dump_record.cpp
+++ b/chromium/third_party/skia/tools/dump_record.cpp
@@ -8,7 +8,6 @@
#include "DumpRecord.h"
#include "SkBitmap.h"
#include "SkCommandLineFlags.h"
-#include "SkDeferredCanvas.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
#include "SkRecordDraw.h"
@@ -24,7 +23,6 @@ DEFINE_bool(optimize2, false, "Run SkRecordOptimize2 before dumping.");
DEFINE_int32(tile, 1000000000, "Simulated tile size.");
DEFINE_bool(timeWithCommand, false, "If true, print time next to command, else in first column.");
DEFINE_string2(write, w, "", "Write the (optimized) picture to the named file.");
-DEFINE_bool(defer, false, "Defer clips and translates");
static void dump(const char* name, int w, int h, const SkRecord& record) {
SkBitmap bitmap;
@@ -56,13 +54,6 @@ int main(int argc, char** argv) {
SkDebugf("Could not read %s as an SkPicture.\n", FLAGS_skps[i]);
return 1;
}
- if (FLAGS_defer) {
- SkPictureRecorder recorder;
- SkDeferredCanvas deferred(recorder.beginRecording(src->cullRect()),
- SkDeferredCanvas::kEager);
- src->playback(&deferred);
- src = recorder.finishRecordingAsPicture();
- }
const int w = SkScalarCeilToInt(src->cullRect().width());
const int h = SkScalarCeilToInt(src->cullRect().height());
diff --git a/chromium/third_party/skia/tools/fiddle/draw.cpp b/chromium/third_party/skia/tools/fiddle/draw.cpp
index 8e94883313b..346d1caf592 100644
--- a/chromium/third_party/skia/tools/fiddle/draw.cpp
+++ b/chromium/third_party/skia/tools/fiddle/draw.cpp
@@ -13,7 +13,8 @@
DrawOptions GetDrawOptions() {
// path *should* be absolute.
static const char path[] = "resources/color_wheel.png";
- return DrawOptions(256, 256, true, true, true, true, true, false, false, path);
+ return DrawOptions(256, 256, true, true, true, true, true, false, false, path,
+ GrMipMapped::kYes, 64, 64, 0, GrMipMapped::kYes);
}
void draw(SkCanvas* canvas) {
canvas->clear(SK_ColorWHITE);
@@ -26,4 +27,26 @@ void draw(SkCanvas* canvas) {
&matrix));
canvas->drawPaint(paint);
SkDebugf("This is text output: %d", 2);
+
+ GrContext* context = canvas->getGrContext();
+ if (context) {
+ sk_sp<SkImage> tmp = SkImage::MakeFromTexture(context,
+ backEndTexture,
+ kTopLeft_GrSurfaceOrigin,
+ kOpaque_SkAlphaType,
+ nullptr);
+
+ // TODO: this sampleCnt parameter here should match that set in the options!
+ sk_sp<SkSurface> tmp2 = SkSurface::MakeFromBackendTexture(context,
+ backEndTextureRenderTarget,
+ kTopLeft_GrSurfaceOrigin,
+ 0, nullptr, nullptr);
+
+ // Note: this surface should only be renderable (i.e., not textureable)
+ sk_sp<SkSurface> tmp3 = SkSurface::MakeFromBackendRenderTarget(context,
+ backEndRenderTarget,
+ kTopLeft_GrSurfaceOrigin,
+ nullptr, nullptr);
+ }
+
}
diff --git a/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp b/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp
index 6ceffc9b9c7..92767d1b401 100644
--- a/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp
+++ b/chromium/third_party/skia/tools/fiddle/fiddle_main.cpp
@@ -11,13 +11,31 @@
#include <string>
#include "SkCommandLineFlags.h"
+#include "SkMipMap.h"
+#include "SkUtils.h"
#include "fiddle_main.h"
DEFINE_double(duration, 1.0, "The total duration, in seconds, of the animation we are drawing.");
DEFINE_double(frame, 1.0, "A double value in [0, 1] that specifies the point in animation to draw.");
+#include "GrBackendSurface.h"
+#include "GrContextPriv.h"
+#include "GrGpu.h"
+
+#include "GrTest.h"
+
+
// Globals externed in fiddle_main.h
+sk_sp<GrTexture> backingTexture; // not externed
+GrBackendTexture backEndTexture;
+
+sk_sp<GrRenderTarget> backingRenderTarget; // not externed
+GrBackendRenderTarget backEndRenderTarget;
+
+sk_sp<GrTexture> backingTextureRenderTarget; // not externed
+GrBackendTexture backEndTextureRenderTarget;
+
SkBitmap source;
sk_sp<SkImage> image;
double duration; // The total duration of the animation in seconds.
@@ -98,6 +116,132 @@ static SkCanvas* prepare_canvas(SkCanvas * canvas) {
return canvas;
}
+static bool setup_backend_objects(GrContext* context,
+ const SkBitmap& bm,
+ const DrawOptions& options) {
+ if (!context) {
+ return false;
+ }
+
+ GrBackend backend = context->contextPriv().getBackend();
+ const GrPixelConfig kConfig = kRGBA_8888_GrPixelConfig;
+
+ GrSurfaceDesc backingDesc;
+ backingDesc.fFlags = kNone_GrSurfaceFlags;
+ backingDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
+ backingDesc.fWidth = bm.width();
+ backingDesc.fHeight = bm.height();
+ backingDesc.fConfig = kConfig;
+ backingDesc.fSampleCnt = 0;
+
+ if (!bm.empty()) {
+ int mipLevelCount = GrMipMapped::kYes == options.fMipMapping
+ ? SkMipMap::ComputeLevelCount(bm.width(), bm.height())
+ : 1;
+ std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
+
+ texels[0].fPixels = bm.getPixels();
+ texels[0].fRowBytes = bm.rowBytes();
+
+ for (int i = 1; i < mipLevelCount; i++) {
+ texels[i].fPixels = nullptr;
+ texels[i].fRowBytes = 0;
+ }
+
+ backingTexture = context->resourceProvider()->createTexture(
+ backingDesc, SkBudgeted::kNo,
+ texels.get(), mipLevelCount,
+ SkDestinationSurfaceColorMode::kLegacy);
+ if (!backingTexture) {
+ return false;
+ }
+
+ backEndTexture = GrTest::CreateBackendTexture(backend,
+ backingDesc.fWidth,
+ backingDesc.fHeight,
+ kConfig,
+ options.fMipMapping,
+ backingTexture->getTextureHandle());
+ if (!backEndTexture.isValid()) {
+ return false;
+ }
+ }
+
+ backingDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+ backingDesc.fWidth = options.fOffScreenWidth;
+ backingDesc.fHeight = options.fOffScreenHeight;
+ backingDesc.fSampleCnt = options.fOffScreenSampleCount;
+
+ SkAutoTMalloc<uint32_t> data(backingDesc.fWidth * backingDesc.fHeight);
+ sk_memset32(data.get(), 0, backingDesc.fWidth * backingDesc.fHeight);
+
+
+ {
+ // This backend object should be renderable but not textureable. Given the limitations
+ // of how we're creating it though it will wind up being secretly textureable.
+ // We use this fact to initialize it with data but don't allow mipmaps
+ GrMipLevel level0 = { data.get(), backingDesc.fWidth*sizeof(uint32_t) };
+
+ sk_sp<GrTexture> tmp = context->resourceProvider()->createTexture(
+ backingDesc, SkBudgeted::kNo,
+ &level0, 1,
+ SkDestinationSurfaceColorMode::kLegacy);
+ if (!tmp || !tmp->asRenderTarget()) {
+ return false;
+ }
+
+ backingRenderTarget = sk_ref_sp(tmp->asRenderTarget());
+
+ backEndRenderTarget = GrTest::CreateBackendRenderTarget(
+ backend,
+ backingDesc.fWidth,
+ backingDesc.fHeight,
+ backingDesc.fSampleCnt, 0,
+ kConfig,
+ backingRenderTarget->getRenderTargetHandle());
+ if (!backEndRenderTarget.isValid()) {
+ return false;
+ }
+ }
+
+ {
+ int mipLevelCount = GrMipMapped::kYes == options.fOffScreenMipMapping
+ ? SkMipMap::ComputeLevelCount(backingDesc.fWidth, backingDesc.fHeight)
+ : 1;
+ std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
+
+ texels[0].fPixels = data.get();
+ texels[0].fRowBytes = backingDesc.fWidth*sizeof(uint32_t);
+
+ for (int i = 1; i < mipLevelCount; i++) {
+ texels[i].fPixels = nullptr;
+ texels[i].fRowBytes = 0;
+ }
+
+ backingTextureRenderTarget = context->resourceProvider()->createTexture(
+ backingDesc, SkBudgeted::kNo,
+ texels.get(), mipLevelCount,
+ SkDestinationSurfaceColorMode::kLegacy);
+ if (!backingTextureRenderTarget || !backingTextureRenderTarget->asRenderTarget()) {
+ return false;
+ }
+
+ backEndTextureRenderTarget = GrTest::CreateBackendTexture(
+ backend,
+ backingDesc.fWidth,
+ backingDesc.fHeight,
+ kConfig,
+ options.fOffScreenMipMapping,
+ backingTextureRenderTarget->getTextureHandle());
+ if (!backEndTextureRenderTarget.isValid()) {
+ return false;
+ }
+ }
+
+
+ return true;
+}
+
int main(int argc, char** argv) {
SkCommandLineFlags::Parse(argc, argv);
duration = FLAGS_duration;
@@ -122,8 +266,7 @@ int main(int argc, char** argv) {
perror("Unable to decode the source image.");
return 1;
}
- SkAssertResult(image->asLegacyBitmap(
- &source, SkImage::kRO_LegacyBitmapMode));
+ SkAssertResult(image->asLegacyBitmap(&source, SkImage::kRO_LegacyBitmapMode));
}
}
sk_sp<SkData> rasterData, gpuData, pdfData, skpData;
@@ -145,10 +288,15 @@ int main(int argc, char** argv) {
rasterData = encode_snapshot(rasterSurface);
}
if (options.gpu) {
- auto grContext = create_grcontext(gGLDriverInfo);
+ sk_sp<GrContext> grContext = create_grcontext(gGLDriverInfo);
if (!grContext) {
fputs("Unable to get GrContext.\n", stderr);
} else {
+ if (!setup_backend_objects(grContext.get(), source, options)) {
+ fputs("Unable to create backend objects.\n", stderr);
+ exit(1);
+ }
+
auto surface = SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kNo, info);
if (!surface) {
fputs("Unable to get render surface.\n", stderr);
diff --git a/chromium/third_party/skia/tools/fiddle/fiddle_main.h b/chromium/third_party/skia/tools/fiddle/fiddle_main.h
index fb9d4094828..5492a424ea7 100644
--- a/chromium/third_party/skia/tools/fiddle/fiddle_main.h
+++ b/chromium/third_party/skia/tools/fiddle/fiddle_main.h
@@ -22,13 +22,22 @@
#include <sstream>
+extern GrBackendTexture backEndTexture;
+extern GrBackendRenderTarget backEndRenderTarget;
+extern GrBackendTexture backEndTextureRenderTarget;
extern SkBitmap source;
extern sk_sp<SkImage> image;
extern double duration; // The total duration of the animation in seconds.
extern double frame; // A value in [0, 1] of where we are in the animation.
struct DrawOptions {
- DrawOptions(int w, int h, bool r, bool g, bool p, bool k, bool srgb, bool f16, bool textOnly, const char* s)
+ DrawOptions(int w, int h, bool r, bool g, bool p, bool k, bool srgb, bool f16,
+ bool textOnly, const char* s,
+ GrMipMapped mipMapping,
+ int offScreenWidth,
+ int offScreenHeight,
+ int offScreenSampleCount,
+ GrMipMapped offScreenMipMapping)
: size(SkISize::Make(w, h))
, raster(r)
, gpu(g)
@@ -38,7 +47,11 @@ struct DrawOptions {
, f16(f16)
, textOnly(textOnly)
, source(s)
- {
+ , fMipMapping(mipMapping)
+ , fOffScreenWidth(offScreenWidth)
+ , fOffScreenHeight(offScreenHeight)
+ , fOffScreenSampleCount(offScreenSampleCount)
+ , fOffScreenMipMapping(offScreenMipMapping) {
// F16 mode is only valid for color correct backends.
SkASSERT(srgb || !f16);
}
@@ -51,6 +64,20 @@ struct DrawOptions {
bool f16;
bool textOnly;
const char* source;
+
+ // This flag is used when a GPU texture resource is created and exposed as a GrBackendTexture.
+ // In this case the resource is created with extra room to accomodate mipmaps.
+ // TODO: The SkImage::makeTextureImage API would need to be widened to allow this to be true
+ // for the non-backend gpu SkImages.
+ GrMipMapped fMipMapping;
+
+ // Parameters for an GPU offscreen resource exposed as a GrBackendRenderTarget
+ int fOffScreenWidth;
+ int fOffScreenHeight;
+ int fOffScreenSampleCount;
+ // TODO: should we also expose stencilBits here? How about the config?
+
+ GrMipMapped fOffScreenMipMapping; // only applicable if the offscreen is also textureable
};
extern DrawOptions GetDrawOptions();
diff --git a/chromium/third_party/skia/tools/fiddle/mesa_context.cpp b/chromium/third_party/skia/tools/fiddle/mesa_context.cpp
deleted file mode 100644
index 89902ec711e..00000000000
--- a/chromium/third_party/skia/tools/fiddle/mesa_context.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "fiddle_main.h"
-
-#include <GL/osmesa.h>
-
-// create_grcontext implementation for Mesa.
-sk_sp<GrContext> create_grcontext(std::ostringstream &driverinfo) {
- // We just leak the OSMesaContext... the process will die soon anyway.
- if (OSMesaContext osMesaContext = OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, nullptr)) {
- static uint32_t buffer[16 * 16];
- OSMesaMakeCurrent(osMesaContext, &buffer, GL_UNSIGNED_BYTE, 16, 16);
- }
- driverinfo << "Mesa";
-
- auto osmesa_get = [](void* ctx, const char name[]) {
- SkASSERT(nullptr == ctx);
- SkASSERT(OSMesaGetCurrentContext());
- return OSMesaGetProcAddress(name);
- };
- sk_sp<const GrGLInterface> mesa(GrGLAssembleInterface(nullptr, osmesa_get));
- if (!mesa) {
- return nullptr;
- }
- return GrContext::MakeGL(mesa.get());
-}
diff --git a/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp b/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp
index 0fc1e1d1868..bebb88b088a 100644
--- a/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp
+++ b/chromium/third_party/skia/tools/flags/SkCommonFlags.cpp
@@ -87,6 +87,10 @@ DEFINE_bool(deltaAA, kDefaultDeltaAA,
DEFINE_bool(forceDeltaAA, false, "Force delta anti-aliasing for all paths.");
+#if SK_SUPPORT_GPU
+DEFINE_bool(cachePathMasks, true, "Allows path mask textures to be cached in GPU configs.");
+#endif
+
bool CollectImages(SkCommandLineFlags::StringArray images, SkTArray<SkString>* output) {
SkASSERT(output);
diff --git a/chromium/third_party/skia/tools/flags/SkCommonFlags.h b/chromium/third_party/skia/tools/flags/SkCommonFlags.h
index 3d4b33e640d..4f93d1974f7 100644
--- a/chromium/third_party/skia/tools/flags/SkCommonFlags.h
+++ b/chromium/third_party/skia/tools/flags/SkCommonFlags.h
@@ -36,6 +36,9 @@ DECLARE_bool(analyticAA);
DECLARE_bool(forceAnalyticAA);
DECLARE_bool(deltaAA);
DECLARE_bool(forceDeltaAA);
+#if SK_SUPPORT_GPU
+DECLARE_bool(cachePathMasks);
+#endif
DECLARE_string(key);
DECLARE_string(properties);
diff --git a/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp b/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
index 16fe914f770..fe9faaef1d7 100644
--- a/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
+++ b/chromium/third_party/skia/tools/flags/SkCommonFlagsConfig.cpp
@@ -86,9 +86,6 @@ static const struct {
{ "angle_gl_es3", "gpu", "api=angle_gl_es3" },
{ "commandbuffer", "gpu", "api=commandbuffer" },
{ "mock", "gpu", "api=mock" }
-#if SK_MESA
- ,{ "mesa", "gpu", "api=mesa" }
-#endif
#ifdef SK_VULKAN
,{ "vk", "gpu", "api=vulkan" }
,{ "vksrgb", "gpu", "api=vulkan,color=srgb" }
@@ -141,9 +138,6 @@ static const char configExtendedHelp[] =
"\t\tangle_gl_es3\t\t\tUse OpenGL ES3 on the ANGLE OpenGL backend.\n"
"\t\tcommandbuffer\t\tUse command buffer.\n"
"\t\tmock\t\tUse mock context.\n"
-#if SK_MESA
- "\t\tmesa\t\t\tUse MESA.\n"
-#endif
#ifdef SK_VULKAN
"\t\tvulkan\t\t\tUse Vulkan.\n"
#endif
@@ -307,12 +301,6 @@ static bool parse_option_gpu_api(const SkString& value,
*outContextType = GrContextFactory::kMock_ContextType;
return true;
}
-#if SK_MESA
- if (value.equals("mesa")) {
- *outContextType = GrContextFactory::kMESA_ContextType;
- return true;
- }
-#endif
#ifdef SK_VULKAN
if (value.equals("vulkan")) {
*outContextType = GrContextFactory::kVulkan_ContextType;
diff --git a/chromium/third_party/skia/tools/gdb/bitmap.py b/chromium/third_party/skia/tools/gdb/bitmap.py
new file mode 100644
index 00000000000..e9e18f973ee
--- /dev/null
+++ b/chromium/third_party/skia/tools/gdb/bitmap.py
@@ -0,0 +1,83 @@
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Visualize bitmaps in gdb.
+
+(gdb) source <path to this file>
+(gdb) sk_bitmap <symbol>
+
+This should pop up a window with the bitmap displayed.
+Right clicking should bring up a menu, allowing the
+bitmap to be saved to a file.
+"""
+
+import gdb
+from enum import Enum
+try:
+ from PIL import Image
+except ImportError:
+ import Image
+
+class ColorType(Enum):
+ unknown = 0
+ alpha_8 = 1
+ rgb_565 = 2
+ argb_4444 = 3
+ rgba_8888 = 4
+ bgra_8888 = 5
+ gray_8 = 6
+ rgba_F16 = 7
+
+class AlphaType(Enum):
+ unknown = 0
+ opaque = 1
+ premul = 2
+ unpremul = 3
+
+class sk_bitmap(gdb.Command):
+ """Displays the content of an SkBitmap image."""
+
+ def __init__(self):
+ super(sk_bitmap, self).__init__('sk_bitmap',
+ gdb.COMMAND_SUPPORT,
+ gdb.COMPLETE_FILENAME)
+
+ def invoke(self, arg, from_tty):
+ frame = gdb.selected_frame()
+ val = frame.read_var(arg)
+ if str(val.type.strip_typedefs()) == 'SkBitmap':
+ pixels = val['fPixels']
+ row_bytes = val['fRowBytes']
+ info = val['fInfo']
+ width = info['fWidth']
+ height = info['fHeight']
+ color_type = info['fColorType']
+ alpha_type = info['fAlphaType']
+
+ process = gdb.selected_inferior()
+ memory_data = process.read_memory(pixels, row_bytes * height)
+ size = (width, height)
+ image = None
+ # See Unpack.c for the values understood after the "raw" parameter.
+ if color_type == ColorType.bgra_8888.value:
+ if alpha_type == AlphaType.unpremul.value:
+ image = Image.frombytes("RGBA", size, memory_data.tobytes(),
+ "raw", "BGRA", row_bytes, 1)
+ elif alpha_type == AlphaType.premul.value:
+ # RGBA instead of RGBa, because Image.show() doesn't work with RGBa.
+ image = Image.frombytes("RGBA", size, memory_data.tobytes(),
+ "raw", "BGRa", row_bytes, 1)
+
+ if image:
+ # Fails on premultiplied alpha, it cannot convert to RGB.
+ image.show()
+ else:
+ print ("Need to add support for %s %s." % (
+ str(ColorType(int(color_type))),
+ str(AlphaType(int(alpha_type)))
+ ))
+
+sk_bitmap()
diff --git a/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp b/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
index b3ca1d929eb..00c4b65edc1 100644
--- a/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
+++ b/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
@@ -14,9 +14,6 @@
#endif
#include "gl/command_buffer/GLTestContext_command_buffer.h"
#include "gl/debug/DebugGLTestContext.h"
-#if SK_MESA
- #include "gl/mesa/GLTestContext_mesa.h"
-#endif
#ifdef SK_VULKAN
#include "vk/VkTestContext.h"
#endif
@@ -55,8 +52,9 @@ GrContextFactory::~GrContextFactory() {
void GrContextFactory::destroyContexts() {
for (Context& context : fContexts) {
+ SkScopeExit restore(nullptr);
if (context.fTestContext) {
- context.fTestContext->makeCurrent();
+ restore = context.fTestContext->makeCurrentAndAutoRestore();
}
if (!context.fGrContext->unique()) {
context.fGrContext->releaseResourcesAndAbandonContext();
@@ -72,7 +70,7 @@ void GrContextFactory::abandonContexts() {
for (Context& context : fContexts) {
if (!context.fAbandoned) {
if (context.fTestContext) {
- context.fTestContext->makeCurrent();
+ auto restore = context.fTestContext->makeCurrentAndAutoRestore();
context.fTestContext->testAbandon();
delete(context.fTestContext);
context.fTestContext = nullptr;
@@ -85,9 +83,10 @@ void GrContextFactory::abandonContexts() {
void GrContextFactory::releaseResourcesAndAbandonContexts() {
for (Context& context : fContexts) {
+ SkScopeExit restore(nullptr);
if (!context.fAbandoned) {
if (context.fTestContext) {
- context.fTestContext->makeCurrent();
+ restore = context.fTestContext->makeCurrentAndAutoRestore();
}
context.fGrContext->releaseResourcesAndAbandonContext();
context.fAbandoned = true;
@@ -116,7 +115,8 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
context.fShareIndex == shareIndex &&
!context.fAbandoned) {
context.fTestContext->makeCurrent();
- return ContextInfo(context.fType, context.fTestContext, context.fGrContext);
+ return ContextInfo(context.fType, context.fTestContext, context.fGrContext,
+ context.fOptions);
}
}
@@ -173,11 +173,6 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
glCtx = CommandBufferGLTestContext::Create(glShareContext);
break;
#endif
-#if SK_MESA
- case kMESA_ContextType:
- glCtx = CreateMesaGLTestContext(glShareContext);
- break;
-#endif
case kNullGL_ContextType:
glCtx = CreateNullGLTestContext(
ContextOverrides::kRequireNVPRSupport & overrides, glShareContext);
@@ -244,7 +239,7 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
default:
return ContextInfo();
}
- testCtx->makeCurrent();
+
SkASSERT(testCtx && testCtx->backend() == backend);
GrContextOptions grOptions = fGlobalOptions;
if (ContextOverrides::kDisableNVPR & overrides) {
@@ -259,7 +254,11 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
if (ContextOverrides::kAvoidStencilBuffers & overrides) {
grOptions.fAvoidStencilBuffers = true;
}
- sk_sp<GrContext> grCtx = testCtx->makeGrContext(grOptions);
+ sk_sp<GrContext> grCtx;
+ {
+ auto restore = testCtx->makeCurrentAndAutoRestore();
+ grCtx = testCtx->makeGrContext(grOptions);
+ }
if (!grCtx.get()) {
return ContextInfo();
}
@@ -288,7 +287,9 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
context.fAbandoned = false;
context.fShareContext = shareContext;
context.fShareIndex = shareIndex;
- return ContextInfo(context.fType, context.fTestContext, context.fGrContext);
+ context.fOptions = grOptions;
+ context.fTestContext->makeCurrent();
+ return ContextInfo(context.fType, context.fTestContext, context.fGrContext, context.fOptions);
}
ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides) {
diff --git a/chromium/third_party/skia/tools/gpu/GrContextFactory.h b/chromium/third_party/skia/tools/gpu/GrContextFactory.h
index 8d3e69c765e..6997ca1337a 100644
--- a/chromium/third_party/skia/tools/gpu/GrContextFactory.h
+++ b/chromium/third_party/skia/tools/gpu/GrContextFactory.h
@@ -39,7 +39,6 @@ public:
kANGLE_GL_ES2_ContextType, //! ANGLE on OpenGL OpenGL ES 2 context.
kANGLE_GL_ES3_ContextType, //! ANGLE on OpenGL OpenGL ES 3 context.
kCommandBuffer_ContextType, //! Chromium command buffer OpenGL ES context.
- kMESA_ContextType, //! MESA OpenGL context
kNullGL_ContextType, //! Non-rendering OpenGL mock context.
kDebugGL_ContextType, //! Non-rendering, state verifying OpenGL context.
kVulkan_ContextType, //! Vulkan
@@ -107,8 +106,6 @@ public:
return "ANGLE GL ES3";
case kCommandBuffer_ContextType:
return "Command Buffer";
- case kMESA_ContextType:
- return "Mesa";
case kNullGL_ContextType:
return "Null GL";
case kDebugGL_ContextType:
@@ -159,6 +156,7 @@ private:
struct Context {
ContextType fType;
ContextOverrides fOverrides;
+ GrContextOptions fOptions;
GrBackend fBackend;
TestContext* fTestContext;
GrContext* fGrContext;
@@ -189,19 +187,18 @@ public:
return static_cast<GLTestContext*>(fTestContext);
}
+ const GrContextOptions& options() const { return fOptions; }
+
private:
- ContextInfo(GrContextFactory::ContextType type,
- TestContext* testContext,
- GrContext* grContext)
- : fType(type)
- , fTestContext(testContext)
- , fGrContext(grContext) {
- }
+ ContextInfo(GrContextFactory::ContextType type, TestContext* testContext, GrContext* grContext,
+ const GrContextOptions& options)
+ : fType(type), fTestContext(testContext), fGrContext(grContext), fOptions(options) {}
GrContextFactory::ContextType fType = GrContextFactory::kGL_ContextType;
// Valid until the factory destroys it via abandonContexts() or destroyContexts().
- TestContext* fTestContext = nullptr;
- GrContext* fGrContext = nullptr;
+ TestContext* fTestContext = nullptr;
+ GrContext* fGrContext = nullptr;
+ GrContextOptions fOptions;
friend class GrContextFactory;
};
diff --git a/chromium/third_party/skia/tools/gpu/GrTest.cpp b/chromium/third_party/skia/tools/gpu/GrTest.cpp
index 3a74b6fe540..47f98a6c209 100644
--- a/chromium/third_party/skia/tools/gpu/GrTest.cpp
+++ b/chromium/third_party/skia/tools/gpu/GrTest.cpp
@@ -55,27 +55,51 @@ void SetupAlwaysEvictAtlas(GrContext* context) {
}
GrBackendTexture CreateBackendTexture(GrBackend backend, int width, int height,
- GrPixelConfig config, GrBackendObject handle) {
+ GrPixelConfig config, GrMipMapped mipMapped,
+ GrBackendObject handle) {
switch (backend) {
#ifdef SK_VULKAN
case kVulkan_GrBackend: {
GrVkImageInfo* vkInfo = (GrVkImageInfo*)(handle);
+ SkASSERT((GrMipMapped::kYes == mipMapped) == (vkInfo->fLevelCount > 1));
return GrBackendTexture(width, height, *vkInfo);
}
#endif
case kOpenGL_GrBackend: {
GrGLTextureInfo* glInfo = (GrGLTextureInfo*)(handle);
- return GrBackendTexture(width, height, config, *glInfo);
+ return GrBackendTexture(width, height, config, mipMapped, *glInfo);
}
case kMock_GrBackend: {
GrMockTextureInfo* mockInfo = (GrMockTextureInfo*)(handle);
- return GrBackendTexture(width, height, config, *mockInfo);
+ return GrBackendTexture(width, height, config, mipMapped, *mockInfo);
}
default:
return GrBackendTexture();
}
}
+GrBackendRenderTarget CreateBackendRenderTarget(GrBackend backend, int width, int height,
+ int sampleCnt, int stencilBits,
+ GrPixelConfig config,
+ GrBackendObject handle) {
+ switch (backend) {
+#ifdef SK_VULKAN
+ case kVulkan_GrBackend: {
+ GrVkImageInfo* vkInfo = (GrVkImageInfo*)(handle);
+ return GrBackendRenderTarget(width, height, sampleCnt, stencilBits, *vkInfo);
+ }
+#endif
+ case kOpenGL_GrBackend: {
+ GrGLFramebufferInfo glInfo;
+ glInfo.fFBOID = handle;
+ return GrBackendRenderTarget(width, height, sampleCnt, stencilBits, config, glInfo);
+ }
+ case kMock_GrBackend: // fall through
+ default:
+ return GrBackendRenderTarget();
+ }
+}
+
} // namespace GrTest
bool GrSurfaceProxy::isWrapped_ForTesting() const {
diff --git a/chromium/third_party/skia/tools/gpu/GrTest.h b/chromium/third_party/skia/tools/gpu/GrTest.h
index d4a4c6dfac3..1134932ad9f 100644
--- a/chromium/third_party/skia/tools/gpu/GrTest.h
+++ b/chromium/third_party/skia/tools/gpu/GrTest.h
@@ -19,7 +19,11 @@ namespace GrTest {
void SetupAlwaysEvictAtlas(GrContext*);
GrBackendTexture CreateBackendTexture(GrBackend, int width, int height,
- GrPixelConfig, GrBackendObject);
+ GrPixelConfig, GrMipMapped, GrBackendObject);
+
+ GrBackendRenderTarget CreateBackendRenderTarget(GrBackend, int width, int height,
+ int sampleCnt, int stencilBits,
+ GrPixelConfig, GrBackendObject);
};
#endif
diff --git a/chromium/third_party/skia/tools/gpu/TestContext.cpp b/chromium/third_party/skia/tools/gpu/TestContext.cpp
index c80c4ea4dfb..f760cc7738a 100644
--- a/chromium/third_party/skia/tools/gpu/TestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/TestContext.cpp
@@ -37,8 +37,15 @@ sk_sp<GrContext> TestContext::makeGrContext(const GrContextOptions&) {
void TestContext::makeCurrent() const { this->onPlatformMakeCurrent(); }
+SkScopeExit TestContext::makeCurrentAndAutoRestore() const {
+ auto asr = SkScopeExit(this->onPlatformGetAutoContextRestore());
+ this->makeCurrent();
+ return asr;
+}
+
void TestContext::swapBuffers() { this->onPlatformSwapBuffers(); }
+
void TestContext::waitOnSyncOrSwap() {
if (!fFenceSync) {
// Fallback on the platform SwapBuffers method for synchronization. This may have no effect.
diff --git a/chromium/third_party/skia/tools/gpu/TestContext.h b/chromium/third_party/skia/tools/gpu/TestContext.h
index 84794f3c34e..5b512db7ba4 100644
--- a/chromium/third_party/skia/tools/gpu/TestContext.h
+++ b/chromium/third_party/skia/tools/gpu/TestContext.h
@@ -9,10 +9,11 @@
#ifndef TestContext_DEFINED
#define TestContext_DEFINED
+#include "../private/SkTemplates.h"
#include "FenceSync.h"
#include "GrTypes.h"
#include "SkRefCnt.h"
-#include "../private/SkTemplates.h"
+#include "SkScopeExit.h"
class GrContext;
struct GrContextOptions;
@@ -45,6 +46,18 @@ public:
void makeCurrent() const;
+ /**
+ * Like makeCurrent() but this returns an object that will restore the previous current
+ * context in its destructor. Useful to undo the effect making this current before returning to
+ * a caller that doesn't expect the current context to be changed underneath it.
+ *
+ * The returned object restores the current context of the same type (e.g. egl, glx, ...) in its
+ * destructor. It is undefined behavior if that context is destroyed before the destructor
+ * executes. If the concept of a current context doesn't make sense for this context type then
+ * the returned object's destructor is a no-op.
+ */
+ SkScopeExit SK_WARN_UNUSED_RESULT makeCurrentAndAutoRestore() const;
+
virtual GrBackend backend() = 0;
virtual GrBackendContext backendContext() = 0;
@@ -94,6 +107,14 @@ protected:
virtual void teardown();
virtual void onPlatformMakeCurrent() const = 0;
+ /**
+ * Subclasses should implement such that the returned function will cause the current context
+ * of this type to be made current again when it is called. It should additionally be the
+ * case that if "this" is already current when this is called, then "this" is destroyed (thereby
+ * setting the null context as current), and then the std::function is called the null context
+ * should remain current.
+ */
+ virtual std::function<void()> onPlatformGetAutoContextRestore() const = 0;
virtual void onPlatformSwapBuffers() const = 0;
private:
diff --git a/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp b/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp
new file mode 100644
index 00000000000..e1130966928
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp
@@ -0,0 +1,455 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GLTestAtlasTextRenderer.h"
+#include "../gl/GLTestContext.h"
+#include "SkBitmap.h"
+#include "TestAtlasTextRenderer.h"
+#include "gl/GrGLDefines.h"
+
+using sk_gpu_test::GLTestContext;
+
+namespace {
+
+class GLTestAtlasTextRenderer : public sk_gpu_test::TestAtlasTextRenderer {
+public:
+ GLTestAtlasTextRenderer(std::unique_ptr<GLTestContext>);
+
+ void* createTexture(AtlasFormat, int width, int height) override;
+
+ void deleteTexture(void* textureHandle) override;
+
+ void setTextureData(void* textureHandle, const void* data, int x, int y, int width, int height,
+ size_t rowBytes) override;
+
+ void drawSDFGlyphs(void* targetHandle, void* textureHandle, const SDFVertex vertices[],
+ int quadCnt) override;
+
+ void* makeTargetHandle(int width, int height) override;
+
+ void targetDeleted(void* targetHandle) override;
+
+ SkBitmap readTargetHandle(void* targetHandle) override;
+
+ void clearTarget(void* targetHandle, uint32_t color) override;
+
+ bool initialized() const { return 0 != fProgram; }
+
+private:
+ struct AtlasTexture {
+ GrGLuint fID;
+ AtlasFormat fFormat;
+ int fWidth;
+ int fHeight;
+ };
+
+ struct Target {
+ GrGLuint fFBOID;
+ GrGLuint fRBID;
+ int fWidth;
+ int fHeight;
+ };
+
+ std::unique_ptr<GLTestContext> fContext;
+ GrGLuint fProgram = 0;
+ GrGLint fDstScaleAndTranslateLocation = 0;
+ GrGLint fAtlasInvSizeLocation = 0;
+ GrGLint fSamplerLocation = 0;
+};
+
+#define callgl(NAME, ...) fContext->gl()->fFunctions.f##NAME(__VA_ARGS__)
+#define checkgl() \
+ do { \
+ static constexpr auto line = __LINE__; \
+ auto error = fContext->gl()->fFunctions.fGetError(); \
+ if (error != GR_GL_NO_ERROR) { \
+ SkDebugf("GL ERROR: 0x%x, line %d\n", error, line); \
+ } \
+ } while (false)
+
+GLTestAtlasTextRenderer::GLTestAtlasTextRenderer(std::unique_ptr<GLTestContext> context)
+ : fContext(std::move(context)) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+ auto vs = callgl(CreateShader, GR_GL_VERTEX_SHADER);
+ static constexpr char kGLVersionString[] = "#version 430 compatibility";
+ static constexpr char kGLESVersionString[] = "#version 300 es";
+ GrGLint lengths[2];
+ const GrGLchar* strings[2];
+ switch (fContext->gl()->fStandard) {
+ case kGL_GrGLStandard:
+ strings[0] = kGLVersionString;
+ lengths[0] = static_cast<GrGLint>(SK_ARRAY_COUNT(kGLVersionString)) - 1;
+ break;
+ case kGLES_GrGLStandard:
+ strings[0] = kGLESVersionString;
+ lengths[0] = static_cast<GrGLint>(SK_ARRAY_COUNT(kGLESVersionString)) - 1;
+ break;
+ default:
+ strings[0] = nullptr;
+ lengths[0] = 0;
+ break;
+ }
+
+ static constexpr const char kVS[] = R"(
+ uniform vec4 uDstScaleAndTranslate;
+ uniform vec2 uAtlasInvSize;
+
+ layout (location = 0) in vec2 inPosition;
+ layout (location = 1) in vec4 inColor;
+ layout (location = 2) in uvec2 inTextureCoords;
+
+ out vec2 vTexCoord;
+ out vec4 vColor;
+ out vec2 vIntTexCoord;
+
+ void main() {
+ vec2 intCoords;
+ // floor(vec2) doesn't seem to work on some ES devices.
+ intCoords.x = floor(float(inTextureCoords.x));
+ intCoords.y = floor(float(inTextureCoords.y));
+ vTexCoord = intCoords * uAtlasInvSize;
+ vIntTexCoord = intCoords;
+ vColor = inColor;
+ gl_Position = vec4(inPosition.x * uDstScaleAndTranslate.x + uDstScaleAndTranslate.y,
+ inPosition.y * uDstScaleAndTranslate.z + uDstScaleAndTranslate.w,
+ 0.0, 1.0);
+ }
+ )";
+ strings[1] = kVS;
+ lengths[1] = SK_ARRAY_COUNT(kVS) - 1;
+ callgl(ShaderSource, vs, 2, strings, lengths);
+ callgl(CompileShader, vs);
+ GrGLint compileStatus;
+ callgl(GetShaderiv, vs, GR_GL_COMPILE_STATUS, &compileStatus);
+ if (compileStatus == GR_GL_FALSE) {
+ GrGLint logLength;
+ callgl(GetShaderiv, vs, GR_GL_INFO_LOG_LENGTH, &logLength);
+ std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
+ log[logLength] = '\0';
+ callgl(GetShaderInfoLog, vs, logLength, &logLength, log.get());
+ SkDebugf("Vertex Shader failed to compile\n%s", log.get());
+ callgl(DeleteShader, vs);
+ return;
+ }
+
+ auto fs = callgl(CreateShader, GR_GL_FRAGMENT_SHADER);
+ static constexpr const char kFS[] = R"(
+ uniform sampler2D uSampler;
+
+ in vec2 vTexCoord;
+ in vec4 vColor;
+ in vec2 vIntTexCoord;
+
+ layout (location = 0) out vec4 outColor;
+
+ void main() {
+ float sdfValue = texture(uSampler, vTexCoord).r;
+ float distance = 7.96875 * (sdfValue - 0.50196078431000002);
+ vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));
+ vec2 Jdx = dFdx(vIntTexCoord);
+ vec2 Jdy = dFdy(vIntTexCoord);
+ float dg_len2 = dot(dist_grad, dist_grad);
+ if (dg_len2 < 0.0001) {
+ dist_grad = vec2(0.7071, 0.7071);
+ } else {
+ dist_grad = dist_grad * inversesqrt(dg_len2);
+ }
+ vec2 grad = vec2(dist_grad.x * Jdx.x + dist_grad.y * Jdy.x,
+ dist_grad.x * Jdx.y + dist_grad.y * Jdy.y);
+ float afwidth = abs(0.65000000000000002 * length(grad));
+ float value = smoothstep(-afwidth, afwidth, distance);
+ outColor = value * vec4(vColor.rgb * vColor.a, vColor.a);
+ }
+ )";
+ strings[1] = kFS;
+ lengths[1] = SK_ARRAY_COUNT(kFS) - 1;
+ callgl(ShaderSource, fs, 2, strings, lengths);
+ callgl(CompileShader, fs);
+ callgl(GetShaderiv, fs, GR_GL_COMPILE_STATUS, &compileStatus);
+ if (compileStatus == GR_GL_FALSE) {
+ GrGLint logLength;
+ callgl(GetShaderiv, fs, GR_GL_INFO_LOG_LENGTH, &logLength);
+ std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
+ log[logLength] = '\0';
+ callgl(GetShaderInfoLog, fs, logLength, &logLength, log.get());
+ SkDebugf("Fragment Shader failed to compile\n%s", log.get());
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ return;
+ }
+
+ fProgram = callgl(CreateProgram);
+ if (!fProgram) {
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ return;
+ }
+
+ callgl(AttachShader, fProgram, vs);
+ callgl(AttachShader, fProgram, fs);
+ callgl(LinkProgram, fProgram);
+ GrGLint linkStatus;
+ callgl(GetProgramiv, fProgram, GR_GL_LINK_STATUS, &linkStatus);
+ if (linkStatus == GR_GL_FALSE) {
+ GrGLint logLength = 0;
+ callgl(GetProgramiv, vs, GR_GL_INFO_LOG_LENGTH, &logLength);
+ std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
+ log[logLength] = '\0';
+ callgl(GetProgramInfoLog, vs, logLength, &logLength, log.get());
+ SkDebugf("Program failed to link\n%s", log.get());
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ callgl(DeleteProgram, fProgram);
+ fProgram = 0;
+ return;
+ }
+ fDstScaleAndTranslateLocation = callgl(GetUniformLocation, fProgram, "uDstScaleAndTranslate");
+ fAtlasInvSizeLocation = callgl(GetUniformLocation, fProgram, "uAtlasInvSize");
+ fSamplerLocation = callgl(GetUniformLocation, fProgram, "uSampler");
+ if (fDstScaleAndTranslateLocation < 0 || fAtlasInvSizeLocation < 0 || fSamplerLocation < 0) {
+ callgl(DeleteShader, vs);
+ callgl(DeleteShader, fs);
+ callgl(DeleteProgram, fProgram);
+ fProgram = 0;
+ }
+
+ checkgl();
+}
+
+inline bool atlas_format_to_gl_types(SkAtlasTextRenderer::AtlasFormat format,
+ GrGLenum* internalFormat, GrGLenum* externalFormat,
+ GrGLenum* type) {
+ switch (format) {
+ case SkAtlasTextRenderer::AtlasFormat::kA8:
+ *internalFormat = GR_GL_R8;
+ *externalFormat = GR_GL_RED;
+ *type = GR_GL_UNSIGNED_BYTE;
+ return true;
+ }
+ return false;
+}
+
+inline int atlas_format_bytes_per_pixel(SkAtlasTextRenderer::AtlasFormat format) {
+ switch (format) {
+ case SkAtlasTextRenderer::AtlasFormat::kA8:
+ return 1;
+ }
+ return 0;
+}
+
+void* GLTestAtlasTextRenderer::createTexture(AtlasFormat format, int width, int height) {
+ GrGLenum internalFormat;
+ GrGLenum externalFormat;
+ GrGLenum type;
+ if (!atlas_format_to_gl_types(format, &internalFormat, &externalFormat, &type)) {
+ return nullptr;
+ }
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ GrGLuint id;
+ callgl(GenTextures, 1, &id);
+ if (!id) {
+ return nullptr;
+ }
+
+ callgl(BindTexture, GR_GL_TEXTURE_2D, id);
+ callgl(TexImage2D, GR_GL_TEXTURE_2D, 0, internalFormat, width, height, 0, externalFormat, type,
+ nullptr);
+ checkgl();
+
+ AtlasTexture* atlas = new AtlasTexture;
+ atlas->fID = id;
+ atlas->fFormat = format;
+ atlas->fWidth = width;
+ atlas->fHeight = height;
+ return atlas;
+}
+
+void GLTestAtlasTextRenderer::deleteTexture(void* textureHandle) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ auto* atlasTexture = reinterpret_cast<const AtlasTexture*>(textureHandle);
+
+ callgl(DeleteTextures, 1, &atlasTexture->fID);
+ checkgl();
+
+ delete atlasTexture;
+}
+
+void GLTestAtlasTextRenderer::setTextureData(void* textureHandle, const void* data, int x, int y,
+ int width, int height, size_t rowBytes) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ auto atlasTexture = reinterpret_cast<const AtlasTexture*>(textureHandle);
+
+ GrGLenum internalFormat;
+ GrGLenum externalFormat;
+ GrGLenum type;
+ if (!atlas_format_to_gl_types(atlasTexture->fFormat, &internalFormat, &externalFormat, &type)) {
+ return;
+ }
+ int bpp = atlas_format_bytes_per_pixel(atlasTexture->fFormat);
+ GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
+ if (static_cast<size_t>(rowLength * bpp) != rowBytes) {
+ return;
+ }
+ callgl(PixelStorei, GR_GL_UNPACK_ALIGNMENT, 1);
+ callgl(PixelStorei, GR_GL_UNPACK_ROW_LENGTH, rowLength);
+ callgl(BindTexture, GR_GL_TEXTURE_2D, atlasTexture->fID);
+ callgl(TexSubImage2D, GR_GL_TEXTURE_2D, 0, x, y, width, height, externalFormat, type, data);
+ checkgl();
+}
+
+void GLTestAtlasTextRenderer::drawSDFGlyphs(void* targetHandle, void* textureHandle,
+ const SDFVertex vertices[], int quadCnt) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ auto target = reinterpret_cast<const Target*>(targetHandle);
+ auto atlas = reinterpret_cast<const AtlasTexture*>(textureHandle);
+
+ callgl(UseProgram, fProgram);
+
+ callgl(ActiveTexture, GR_GL_TEXTURE0);
+ callgl(BindTexture, GR_GL_TEXTURE_2D, atlas->fID);
+ callgl(TexParameteri, GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_LINEAR);
+ callgl(TexParameteri, GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_LINEAR);
+
+ float uniformScaleAndTranslate[4] = {2.f / target->fWidth, -1.f, 2.f / target->fHeight, -1.f};
+ callgl(Uniform4fv, fDstScaleAndTranslateLocation, 1, uniformScaleAndTranslate);
+ callgl(Uniform2f, fAtlasInvSizeLocation, 1.f / atlas->fWidth, 1.f / atlas->fHeight);
+ callgl(Uniform1i, fSamplerLocation, 0);
+
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
+ callgl(Viewport, 0, 0, target->fWidth, target->fHeight);
+
+ callgl(Enable, GR_GL_BLEND);
+ callgl(BlendFunc, GR_GL_ONE, GR_GL_ONE_MINUS_SRC_ALPHA);
+ callgl(Disable, GR_GL_DEPTH_TEST);
+
+ callgl(BindVertexArray, 0);
+ callgl(BindBuffer, GR_GL_ARRAY_BUFFER, 0);
+ callgl(BindBuffer, GR_GL_ELEMENT_ARRAY_BUFFER, 0);
+ callgl(VertexAttribPointer, 0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(SDFVertex), vertices);
+ size_t colorOffset = 2 * sizeof(float);
+ callgl(VertexAttribPointer, 1, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE, sizeof(SDFVertex),
+ reinterpret_cast<const char*>(vertices) + colorOffset);
+ size_t texOffset = colorOffset + sizeof(uint32_t);
+ callgl(VertexAttribIPointer, 2, 2, GR_GL_UNSIGNED_SHORT, sizeof(SDFVertex),
+ reinterpret_cast<const char*>(vertices) + texOffset);
+ callgl(EnableVertexAttribArray, 0);
+ callgl(EnableVertexAttribArray, 1);
+ callgl(EnableVertexAttribArray, 2);
+
+ std::unique_ptr<uint16_t[]> indices(new uint16_t[quadCnt * 6]);
+ for (int q = 0; q < quadCnt; ++q) {
+ indices[q * 6 + 0] = 0 + 4 * q;
+ indices[q * 6 + 1] = 1 + 4 * q;
+ indices[q * 6 + 2] = 2 + 4 * q;
+ indices[q * 6 + 3] = 2 + 4 * q;
+ indices[q * 6 + 4] = 1 + 4 * q;
+ indices[q * 6 + 5] = 3 + 4 * q;
+ }
+ callgl(DrawElements, GR_GL_TRIANGLES, 6 * quadCnt, GR_GL_UNSIGNED_SHORT, indices.get());
+ checkgl();
+}
+
+void* GLTestAtlasTextRenderer::makeTargetHandle(int width, int height) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ GrGLuint fbo;
+ callgl(GenFramebuffers, 1, &fbo);
+ if (!fbo) {
+ return nullptr;
+ }
+ GrGLuint rb;
+ callgl(GenRenderbuffers, 1, &rb);
+ if (!rb) {
+ callgl(DeleteFramebuffers, 1, &fbo);
+ return nullptr;
+ }
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, fbo);
+ callgl(BindRenderbuffer, GR_GL_RENDERBUFFER, rb);
+ callgl(RenderbufferStorage, GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height);
+ callgl(FramebufferRenderbuffer, GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER,
+ rb);
+ GrGLenum status = callgl(CheckFramebufferStatus, GR_GL_FRAMEBUFFER);
+ if (GR_GL_FRAMEBUFFER_COMPLETE != status) {
+ callgl(DeleteFramebuffers, 1, &fbo);
+ callgl(DeleteRenderbuffers, 1, &rb);
+ return nullptr;
+ }
+ callgl(Disable, GR_GL_SCISSOR_TEST);
+ callgl(ClearColor, 0, 0, 0, 0.0);
+ callgl(Clear, GR_GL_COLOR_BUFFER_BIT);
+ checkgl();
+ Target* target = new Target;
+ target->fFBOID = fbo;
+ target->fRBID = rb;
+ target->fWidth = width;
+ target->fHeight = height;
+ return target;
+}
+
+void GLTestAtlasTextRenderer::targetDeleted(void* targetHandle) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ Target* target = reinterpret_cast<Target*>(targetHandle);
+ callgl(DeleteFramebuffers, 1, &target->fFBOID);
+ callgl(DeleteRenderbuffers, 1, &target->fRBID);
+ delete target;
+}
+
+SkBitmap GLTestAtlasTextRenderer::readTargetHandle(void* targetHandle) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ Target* target = reinterpret_cast<Target*>(targetHandle);
+
+ auto info =
+ SkImageInfo::Make(target->fWidth, target->fHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ SkBitmap bmp;
+ bmp.setInfo(info, sizeof(uint32_t) * target->fWidth);
+ bmp.allocPixels();
+
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
+ callgl(ReadPixels, 0, 0, target->fWidth, target->fHeight, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
+ bmp.getPixels());
+ checkgl();
+ return bmp;
+}
+
+void GLTestAtlasTextRenderer::clearTarget(void* targetHandle, uint32_t color) {
+ auto restore = fContext->makeCurrentAndAutoRestore();
+
+ Target* target = reinterpret_cast<Target*>(targetHandle);
+ callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
+ callgl(Disable, GR_GL_SCISSOR_TEST);
+ float r = ((color >> 0) & 0xff) / 255.f;
+ float g = ((color >> 8) & 0xff) / 255.f;
+ float b = ((color >> 16) & 0xff) / 255.f;
+ float a = ((color >> 24) & 0xff) / 255.f;
+ callgl(ClearColor, r, g, b, a);
+ callgl(Clear, GR_GL_COLOR_BUFFER_BIT);
+}
+
+} // anonymous namespace
+
+namespace sk_gpu_test {
+
+sk_sp<TestAtlasTextRenderer> MakeGLTestAtlasTextRenderer() {
+ std::unique_ptr<GLTestContext> context(CreatePlatformGLTestContext(kGL_GrGLStandard));
+ if (!context) {
+ context.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
+ }
+ if (!context) {
+ return nullptr;
+ }
+ auto restorer = context->makeCurrentAndAutoRestore();
+ auto renderer = sk_make_sp<GLTestAtlasTextRenderer>(std::move(context));
+ return renderer->initialized() ? std::move(renderer) : nullptr;
+}
+
+} // namespace sk_gpu_test
diff --git a/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h b/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h
new file mode 100644
index 00000000000..df01b345de2
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GLTestAtlasTextRenderer_DEFINED
+#define GLTestAtlasTextRenderer_DEFINED
+
+#include "SkRefCnt.h"
+
+namespace sk_gpu_test {
+
+class TestAtlasTextRenderer;
+
+/**
+ * Creates a TestAtlasTextRenderer that uses its own OpenGL context to implement
+ * SkAtlasTextRenderer.
+ */
+sk_sp<TestAtlasTextRenderer> MakeGLTestAtlasTextRenderer();
+
+} // namespace sk_gpu_test
+
+#endif
diff --git a/chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h b/chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h
new file mode 100644
index 00000000000..6ba43260648
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef TestAtlasTextRenderer_DEFINED
+#define TestAtlasTextRenderer_DEFINED
+
+#include "SkAtlasTextRenderer.h"
+#include "SkBitmap.h"
+
+namespace sk_gpu_test {
+
+class TestContext;
+
+/**
+ * Base class for implementations of SkAtlasTextRenderer in order to test the SkAtlasText APIs.
+ * Adds a helper for creating SkAtlasTextTargets and to read back the contents of a target as a
+ * bitmap.
+ */
+class TestAtlasTextRenderer : public SkAtlasTextRenderer {
+public:
+ /** Returns a handle that can be used to construct a SkAtlasTextTarget instance. */
+ virtual void* makeTargetHandle(int width, int height) = 0;
+
+ /** Makes a SkBitmap of the target handle's contents. */
+ virtual SkBitmap readTargetHandle(void* targetHandle) = 0;
+
+ /** Clears the target to the specified color, encoded as RGBA (low to high byte order) */
+ virtual void clearTarget(void* targetHandle, uint32_t color) = 0;
+};
+
+} // namespace sk_gpu_test
+
+#endif
diff --git a/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp b/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
index 52cc5128dad..3b55c40bac9 100644
--- a/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
@@ -34,6 +34,16 @@ struct Libs {
void* fEGLLib;
};
+std::function<void()> context_restorer() {
+ auto display = eglGetCurrentDisplay();
+ auto dsurface = eglGetCurrentSurface(EGL_DRAW);
+ auto rsurface = eglGetCurrentSurface(EGL_READ);
+ auto context = eglGetCurrentContext();
+ return [display, dsurface, rsurface, context] {
+ eglMakeCurrent(display, dsurface, rsurface, context);
+ };
+}
+
static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
const Libs* libs = reinterpret_cast<const Libs*>(ctx);
GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name);
@@ -87,6 +97,7 @@ private:
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
@@ -214,6 +225,7 @@ ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
+ SkScopeExit restorer(context_restorer());
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Could not set the context.");
this->destroyGLContext();
@@ -320,7 +332,10 @@ std::unique_ptr<sk_gpu_test::GLTestContext> ANGLEGLContext::makeNew() const {
void ANGLEGLContext::destroyGLContext() {
if (EGL_NO_DISPLAY != fDisplay) {
- eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (eglGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
if (EGL_NO_CONTEXT != fContext) {
eglDestroyContext(fDisplay, fContext);
@@ -355,6 +370,13 @@ void ANGLEGLContext::onPlatformMakeCurrent() const {
}
}
+std::function<void()> ANGLEGLContext::onPlatformGetAutoContextRestore() const {
+ if (eglGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void ANGLEGLContext::onPlatformSwapBuffers() const {
if (!eglSwapBuffers(fDisplay, fSurface)) {
SkDebugf("Could not complete eglSwapBuffers.\n");
diff --git a/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp b/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
index 54845fc28b4..be2b6ad5e69 100644
--- a/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
@@ -10,11 +10,14 @@
#include "SkMutex.h"
#include "SkOnce.h"
+#include "SkTLS.h"
#include "gl/GrGLInterface.h"
#include "gl/GrGLAssembleInterface.h"
#include "gl/command_buffer/GLTestContext_command_buffer.h"
#include "../ports/SkOSLibrary.h"
+namespace {
+
typedef void *EGLDisplay;
typedef unsigned int EGLBoolean;
typedef void *EGLConfig;
@@ -25,6 +28,7 @@ typedef void* EGLNativeDisplayType;
typedef void* EGLNativeWindowType;
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
#define EGL_FALSE 0
+#define EGL_TRUE 1
#define EGL_OPENGL_ES2_BIT 0x0004
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
#define EGL_NO_SURFACE ((EGLSurface)0)
@@ -45,6 +49,8 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void);
#define EGL_NONE 0x3038
#define EGL_WIDTH 0x3057
#define EGL_HEIGHT 0x3056
+#define EGL_DRAW 0x3059
+#define EGL_READ 0x305A
typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id);
typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor);
@@ -77,7 +83,6 @@ static GetProcAddressProc gfGetProcAddress = nullptr;
static void* gLibrary = nullptr;
static bool gfFunctionsLoadedSuccessfully = false;
-namespace {
static void load_command_buffer_functions() {
if (!gLibrary) {
static constexpr const char* libName =
@@ -104,12 +109,11 @@ static void load_command_buffer_functions() {
gfSwapBuffers = (SwapBuffersProc)GetProcedureAddress(gLibrary, "eglSwapBuffers");
gfGetProcAddress = (GetProcAddressProc)GetProcedureAddress(gLibrary, "eglGetProcAddress");
- gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate &&
- gfChooseConfig && gfCreateWindowSurface &&
- gfCreatePbufferSurface && gfDestroySurface &&
- gfCreateContext && gfDestroyContext && gfMakeCurrent &&
- gfSwapBuffers && gfGetProcAddress;
-
+ gfFunctionsLoadedSuccessfully =
+ gfGetDisplay && gfInitialize && gfTerminate && gfChooseConfig &&
+ gfCreateWindowSurface && gfCreatePbufferSurface && gfDestroySurface &&
+ gfCreateContext && gfDestroyContext && gfMakeCurrent && gfSwapBuffers &&
+ gfGetProcAddress;
}
}
}
@@ -134,6 +138,80 @@ static const GrGLInterface* create_command_buffer_interface() {
return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc);
}
+
+// The command buffer does not correctly implement eglGetCurrent. It always returns EGL_NO_<foo>.
+// So we implement them ourselves and hook eglMakeCurrent to store the current values in TLS.
+class TLSCurrentObjects {
+public:
+ static EGLDisplay CurrentDisplay() {
+ if (auto objects = Get()) {
+ return objects->fDisplay;
+ }
+ return EGL_NO_DISPLAY;
+ }
+
+ static EGLSurface CurrentSurface(EGLint readdraw) {
+ if (auto objects = Get()) {
+ switch (readdraw) {
+ case EGL_DRAW:
+ return objects->fDrawSurface;
+ case EGL_READ:
+ return objects->fReadSurface;
+ default:
+ return EGL_NO_SURFACE;
+ }
+ }
+ return EGL_NO_SURFACE;
+ }
+
+ static EGLContext CurrentContext() {
+ if (auto objects = Get()) {
+ return objects->fContext;
+ }
+ return EGL_NO_CONTEXT;
+ }
+
+ static EGLBoolean MakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read,
+ EGLContext ctx) {
+ if (gfFunctionsLoadedSuccessfully && EGL_TRUE == gfMakeCurrent(display, draw, read, ctx)) {
+ if (auto objects = Get()) {
+ objects->fDisplay = display;
+ objects->fDrawSurface = draw;
+ objects->fReadSurface = read;
+ objects->fContext = ctx;
+ }
+ return EGL_TRUE;
+ }
+ return EGL_FALSE;
+
+ }
+
+private:
+ EGLDisplay fDisplay = EGL_NO_DISPLAY;
+ EGLSurface fReadSurface = EGL_NO_SURFACE;
+ EGLSurface fDrawSurface = EGL_NO_SURFACE;
+ EGLContext fContext = EGL_NO_CONTEXT;
+
+ static TLSCurrentObjects* Get() {
+ return (TLSCurrentObjects*) SkTLS::Get(TLSCreate, TLSDelete);
+ }
+ static void* TLSCreate() { return new TLSCurrentObjects(); }
+ static void TLSDelete(void* objs) { delete (TLSCurrentObjects*)objs; }
+};
+
+std::function<void()> context_restorer() {
+ if (!gfFunctionsLoadedSuccessfully) {
+ return nullptr;
+ }
+ auto display = TLSCurrentObjects::CurrentDisplay();
+ auto dsurface = TLSCurrentObjects::CurrentSurface(EGL_DRAW);
+ auto rsurface = TLSCurrentObjects::CurrentSurface(EGL_READ);
+ auto context = TLSCurrentObjects::CurrentContext();
+ return [display, dsurface, rsurface, context] {
+ TLSCurrentObjects::MakeCurrent(display, dsurface, rsurface, context);
+ };
+}
+
} // anonymous namespace
namespace sk_gpu_test {
@@ -204,7 +282,8 @@ CommandBufferGLTestContext::CommandBufferGLTestContext(CommandBufferGLTestContex
return;
}
- if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+ SkScopeExit restorer(context_restorer());
+ if (!TLSCurrentObjects::MakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Command Buffer: Could not make EGL context current.\n");
this->destroyGLContext();
return;
@@ -237,15 +316,19 @@ void CommandBufferGLTestContext::destroyGLContext() {
if (EGL_NO_DISPLAY == fDisplay) {
return;
}
+ bool wasCurrent = false;
if (EGL_NO_CONTEXT != fContext) {
+ wasCurrent = (TLSCurrentObjects::CurrentContext() == fContext);
gfDestroyContext(fDisplay, fContext);
fContext = EGL_NO_CONTEXT;
}
- // Call MakeCurrent after destroying the context, so that the EGL implementation knows that
- // the context is not used anymore after it is released from being current. This way
- // command buffer does not need to abandon the context before destruction, and no
- // client-side errors are printed.
- gfMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (wasCurrent) {
+ // Call MakeCurrent after destroying the context, so that the EGL implementation knows that
+ // the context is not used anymore after it is released from being current.This way the
+ // command buffer does not need to abandon the context before destruction, and no
+ // client-side errors are printed.
+ TLSCurrentObjects::MakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
if (EGL_NO_SURFACE != fSurface) {
gfDestroySurface(fDisplay, fSurface);
@@ -258,11 +341,18 @@ void CommandBufferGLTestContext::onPlatformMakeCurrent() const {
if (!gfFunctionsLoadedSuccessfully) {
return;
}
- if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
+ if (!TLSCurrentObjects::MakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Command Buffer: Could not make EGL context current.\n");
}
}
+std::function<void()> CommandBufferGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (!gfFunctionsLoadedSuccessfully || TLSCurrentObjects::CurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void CommandBufferGLTestContext::onPlatformSwapBuffers() const {
if (!gfFunctionsLoadedSuccessfully) {
return;
@@ -288,7 +378,7 @@ void CommandBufferGLTestContext::presentCommandBuffer() {
}
bool CommandBufferGLTestContext::makeCurrent() {
- return gfMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
+ return TLSCurrentObjects::MakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
}
int CommandBufferGLTestContext::getStencilBits() {
diff --git a/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h b/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
index 7582f163516..6a631be8fbf 100644
--- a/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
+++ b/chromium/third_party/skia/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
@@ -42,6 +42,8 @@ private:
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
+
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char *name) const override;
diff --git a/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp b/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
index 3cecd07a0ad..e28a3a7f13d 100644
--- a/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/debug/DebugGLTestContext.cpp
@@ -982,7 +982,8 @@ private:
case GR_GL_COMPILE_STATUS:
*params = GR_GL_TRUE;
break;
- case GR_GL_INFO_LOG_LENGTH:
+ case GR_GL_INFO_LOG_LENGTH: // fallthru
+ case GL_PROGRAM_BINARY_LENGTH:
*params = 0;
break;
// we don't expect any other pnames
@@ -1202,6 +1203,7 @@ public:
private:
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
};
diff --git a/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
index c006098d2fb..4a09d2202a2 100644
--- a/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
@@ -39,6 +39,16 @@ private:
typedef sk_gpu_test::FenceSync INHERITED;
};
+std::function<void()> context_restorer() {
+ auto display = eglGetCurrentDisplay();
+ auto dsurface = eglGetCurrentSurface(EGL_DRAW);
+ auto rsurface = eglGetCurrentSurface(EGL_READ);
+ auto context = eglGetCurrentContext();
+ return [display, dsurface, rsurface, context] {
+ eglMakeCurrent(display, dsurface, rsurface, context);
+ };
+}
+
class EGLGLTestContext : public sk_gpu_test::GLTestContext {
public:
EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext);
@@ -53,6 +63,7 @@ private:
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -168,6 +179,7 @@ EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext*
continue;
}
+ SkScopeExit restorer(context_restorer());
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError());
this->destroyGLContext();
@@ -199,9 +211,11 @@ EGLGLTestContext::~EGLGLTestContext() {
void EGLGLTestContext::destroyGLContext() {
if (fDisplay) {
- eglMakeCurrent(fDisplay, 0, 0, 0);
-
if (fContext) {
+ if (eglGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
eglDestroyContext(fDisplay, fContext);
fContext = EGL_NO_CONTEXT;
}
@@ -237,7 +251,6 @@ GrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
return 0;
}
-#ifndef EGL_NO_IMAGE_EXTERNAL
typedef GrGLvoid (*EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
@@ -246,24 +259,21 @@ GrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
return 0;
}
GrGLuint texID;
- glGenTextures(1, &texID);
+ GR_GL_CALL(this->gl(), GenTextures(1, &texID));
if (!texID) {
return 0;
}
- glBindTexture(GR_GL_TEXTURE_EXTERNAL, texID);
- if (glGetError() != GR_GL_NO_ERROR) {
- glDeleteTextures(1, &texID);
+ GR_GL_CALL_NOERRCHECK(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
+ if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
- if (glGetError() != GR_GL_NO_ERROR) {
- glDeleteTextures(1, &texID);
+ if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
return texID;
-#else
- return 0;
-#endif //EGL_NO_IMAGE_EXTERNAL
}
std::unique_ptr<sk_gpu_test::GLTestContext> EGLGLTestContext::makeNew() const {
@@ -281,6 +291,13 @@ void EGLGLTestContext::onPlatformMakeCurrent() const {
}
}
+std::function<void()> EGLGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (eglGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void EGLGLTestContext::onPlatformSwapBuffers() const {
if (!eglSwapBuffers(fDisplay, fSurface)) {
SkDebugf("Could not complete eglSwapBuffers.\n");
diff --git a/chromium/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp b/chromium/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp
index 76b6d216617..066784df691 100644
--- a/chromium/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp
@@ -62,6 +62,7 @@ private:
GLXContext glxSharedContext);
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -90,11 +91,27 @@ static Display* get_display() {
return ad->display();
}
+std::function<void()> context_restorer() {
+ auto display = glXGetCurrentDisplay();
+ auto drawable = glXGetCurrentDrawable();
+ auto context = glXGetCurrentContext();
+ // On some systems calling glXMakeCurrent with a null display crashes.
+ if (!display) {
+ display = get_display();
+ }
+ return [display, drawable, context] { glXMakeCurrent(display, drawable, context); };
+}
+
GLXGLTestContext::GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* shareContext)
: fContext(nullptr)
, fDisplay(nullptr)
, fPixmap(0)
, fGlxPixmap(0) {
+ // We cross our fingers that this is the first X call in the program and that if the application
+ // is actually threaded that this succeeds.
+ static SkOnce gOnce;
+ gOnce([] { XInitThreads(); });
+
fDisplay = get_display();
GLXContext glxShareContext = shareContext ? shareContext->fContext : nullptr;
@@ -214,6 +231,7 @@ GLXGLTestContext::GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext*
//SkDebugf("Direct GLX rendering context obtained.\n");
}
+ SkScopeExit restorer(context_restorer());
//SkDebugf("Making context current.\n");
if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
SkDebugf("Could not set the context.\n");
@@ -245,9 +263,11 @@ GLXGLTestContext::~GLXGLTestContext() {
void GLXGLTestContext::destroyGLContext() {
if (fDisplay) {
- glXMakeCurrent(fDisplay, 0, 0);
-
if (fContext) {
+ if (glXGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ glXMakeContextCurrent(fDisplay, None, None, nullptr);
+ }
glXDestroyContext(fDisplay, fContext);
fContext = nullptr;
}
@@ -334,6 +354,13 @@ void GLXGLTestContext::onPlatformMakeCurrent() const {
}
}
+std::function<void()> GLXGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (glXGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void GLXGLTestContext::onPlatformSwapBuffers() const {
glXSwapBuffers(fDisplay, fGlxPixmap);
}
diff --git a/chromium/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm b/chromium/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
index e897e8c7c40..65d28614832 100644
--- a/chromium/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
+++ b/chromium/third_party/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
@@ -14,6 +14,11 @@
namespace {
+std::function<void()> context_restorer() {
+ EAGLContext* context = [EAGLContext currentContext];
+ return [context] { [EAGLContext setCurrentContext:context]; };
+}
+
class IOSGLTestContext : public sk_gpu_test::GLTestContext {
public:
IOSGLTestContext(IOSGLTestContext* shareContext);
@@ -23,6 +28,7 @@ private:
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -41,6 +47,7 @@ IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext)
} else {
fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
}
+ SkScopeExit restorer(context_restorer());
[EAGLContext setCurrentContext:fEAGLContext];
sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
@@ -70,6 +77,7 @@ IOSGLTestContext::~IOSGLTestContext() {
void IOSGLTestContext::destroyGLContext() {
if (fEAGLContext) {
if ([EAGLContext currentContext] == fEAGLContext) {
+ // This will ensure that the context is immediately deleted.
[EAGLContext setCurrentContext:nil];
}
fEAGLContext = nil;
@@ -86,6 +94,13 @@ void IOSGLTestContext::onPlatformMakeCurrent() const {
}
}
+std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const {
+ if ([EAGLContext currentContext] == fEAGLContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void IOSGLTestContext::onPlatformSwapBuffers() const { }
GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const {
diff --git a/chromium/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp b/chromium/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
index a94f503d48a..9f1c61e5648 100644
--- a/chromium/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
@@ -14,6 +14,12 @@
#include <dlfcn.h>
namespace {
+
+std::function<void()> context_restorer() {
+ auto context = CGLGetCurrentContext();
+ return [context] { CGLSetCurrentContext(context); };
+}
+
class MacGLTestContext : public sk_gpu_test::GLTestContext {
public:
MacGLTestContext(MacGLTestContext* shareContext);
@@ -23,6 +29,7 @@ private:
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
@@ -58,6 +65,7 @@ MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext)
return;
}
+ SkScopeExit restorer(context_restorer());
CGLSetCurrentContext(fContext);
sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
@@ -86,6 +94,10 @@ MacGLTestContext::~MacGLTestContext() {
void MacGLTestContext::destroyGLContext() {
if (fContext) {
+ if (CGLGetCurrentContext() == fContext) {
+ // This will ensure that the context is immediately deleted.
+ CGLSetCurrentContext(nullptr);
+ }
CGLReleaseContext(fContext);
fContext = nullptr;
}
@@ -98,6 +110,13 @@ void MacGLTestContext::onPlatformMakeCurrent() const {
CGLSetCurrentContext(fContext);
}
+std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (CGLGetCurrentContext() == fContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void MacGLTestContext::onPlatformSwapBuffers() const {
CGLFlushDrawable(fContext);
}
diff --git a/chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp b/chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
deleted file mode 100644
index 5d0014b82c4..00000000000
--- a/chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <GL/osmesa.h>
-
-#include "gl/mesa/GLTestContext_mesa.h"
-#include "gl/GrGLDefines.h"
-
-#include "gl/GrGLAssembleInterface.h"
-#include "gl/GrGLUtil.h"
-#include "osmesa_wrapper.h"
-
-namespace {
-
-static GrGLFuncPtr osmesa_get(void* ctx, const char name[]) {
- SkASSERT(nullptr == ctx);
- SkASSERT(OSMesaGetCurrentContext());
- return OSMesaGetProcAddress(name);
-}
-
-static const GrGLInterface* create_mesa_interface() {
- if (nullptr == OSMesaGetCurrentContext()) {
- return nullptr;
- }
- return GrGLAssembleInterface(nullptr, osmesa_get);
-}
-
-static const GrGLint gBOGUS_SIZE = 16;
-
-class MesaGLContext : public sk_gpu_test::GLTestContext {
-private:
- typedef intptr_t Context;
-
-public:
- MesaGLContext(MesaGLContext* shareContext);
- ~MesaGLContext() override;
-
-private:
- void destroyGLContext();
-
- void onPlatformMakeCurrent() const override;
-
- void onPlatformSwapBuffers() const override;
-
- GrGLFuncPtr onPlatformGetProcAddress(const char *) const override;
-
- Context fContext;
- GrGLubyte *fImage;
-};
-
-MesaGLContext::MesaGLContext(MesaGLContext* shareContext)
- : fContext(static_cast<Context>(0))
- , fImage(nullptr) {
- GR_STATIC_ASSERT(sizeof(Context) == sizeof(OSMesaContext));
- OSMesaContext mesaShareContext = shareContext ? (OSMesaContext)(shareContext->fContext)
- : nullptr;
-
- /* Create an RGBA-mode context */
-#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
- /* specify Z, stencil, accum sizes */
- fContext = (Context)OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, mesaShareContext);
-#else
- fContext = (Context) OSMesaCreateContext(OSMESA_BGRA, mesaShareContext);
-#endif
- if (!fContext) {
- SkDebugf("OSMesaCreateContext failed!\n");
- this->destroyGLContext();
- return;
- }
- // Allocate the image buffer
- fImage = (GrGLubyte *) sk_malloc_throw(gBOGUS_SIZE * gBOGUS_SIZE *
- 4 * sizeof(GrGLubyte));
- if (!fImage) {
- SkDebugf("Alloc image buffer failed!\n");
- this->destroyGLContext();
- return;
- }
-
- // Bind the buffer to the context and make it current
- if (!OSMesaMakeCurrent((OSMesaContext) fContext,
- fImage,
- GR_GL_UNSIGNED_BYTE,
- gBOGUS_SIZE,
- gBOGUS_SIZE)) {
- SkDebugf("OSMesaMakeCurrent failed!\n");
- this->destroyGLContext();
- return;
- }
-
- sk_sp<const GrGLInterface> gl(create_mesa_interface());
- if (nullptr == gl.get()) {
- SkDebugf("Could not create GL interface!\n");
- this->destroyGLContext();
- return;
- }
-
- if (!gl->validate()) {
- SkDebugf("Could not validate GL interface!\n");
- this->destroyGLContext();
- return;
- }
-
- this->init(gl.release());
-}
-
-MesaGLContext::~MesaGLContext() {
- this->teardown();
- this->destroyGLContext();
-}
-
-void MesaGLContext::destroyGLContext() {
- if (fImage) {
- sk_free(fImage);
- fImage = nullptr;
- }
-
- if (fContext) {
- OSMesaDestroyContext((OSMesaContext) fContext);
- fContext = static_cast<Context>(0);
- }
-}
-
-
-void MesaGLContext::onPlatformMakeCurrent() const {
- if (fContext) {
- if (!OSMesaMakeCurrent((OSMesaContext) fContext, fImage,
- GR_GL_UNSIGNED_BYTE, gBOGUS_SIZE, gBOGUS_SIZE)) {
- SkDebugf("Could not make MESA context current.");
- }
- }
-}
-
-void MesaGLContext::onPlatformSwapBuffers() const { }
-
-GrGLFuncPtr MesaGLContext::onPlatformGetProcAddress(const char *procName) const {
- return OSMesaGetProcAddress(procName);
-}
-} // anonymous namespace
-
-
-namespace sk_gpu_test {
-GLTestContext *CreateMesaGLTestContext(GLTestContext* shareContext) {
- MesaGLContext* mesaShareContext = reinterpret_cast<MesaGLContext*>(shareContext);
- MesaGLContext *ctx = new MesaGLContext(mesaShareContext);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
-}
-} // sk_gpu_test
diff --git a/chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h b/chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h
deleted file mode 100644
index 40184aa7ea2..00000000000
--- a/chromium/third_party/skia/tools/gpu/gl/mesa/GLTestContext_mesa.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef GLTestContext_mesa_DEFINED
-#define GLTestContext_mesa_DEFINED
-
-#include "gl/GLTestContext.h"
-
-namespace sk_gpu_test {
-GLTestContext* CreateMesaGLTestContext(GLTestContext* shareContext);
-} // namespace sk_gpu_test
-
-#endif
diff --git a/chromium/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h b/chromium/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h
deleted file mode 100644
index 70de99376d7..00000000000
--- a/chromium/third_party/skia/tools/gpu/gl/mesa/osmesa_wrapper.h
+++ /dev/null
@@ -1,16 +0,0 @@
-
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// Older versions of XQuartz have a bug where a header included by osmesa.h
-// defines GL_GLEXT_PROTOTYPES. This will cause a redefinition warning if
-// the file that includes osmesa.h already defined it. XCode 3 uses a version
-// of gcc (4.2.1) that does not support the diagnostic pragma to disable a
-// warning (added in 4.2.4). So we use the system_header pragma to shut GCC
-// up about warnings in osmesa.h
-#pragma GCC system_header
-#include <GL/osmesa.h>
diff --git a/chromium/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp b/chromium/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp
index 894de0709a6..9e7279b501a 100644
--- a/chromium/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/null/NullGLTestContext.cpp
@@ -22,6 +22,7 @@ public:
private:
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
};
diff --git a/chromium/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp b/chromium/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
index 0e97153794c..5fc355a22a1 100644
--- a/chromium/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
@@ -16,6 +16,12 @@
namespace {
+std::function<void()> context_restorer() {
+ auto glrc = wglGetCurrentContext();
+ auto dc = wglGetCurrentDC();
+ return [glrc, dc] { wglMakeCurrent(dc, glrc); };
+}
+
class WinGLTestContext : public sk_gpu_test::GLTestContext {
public:
WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
@@ -25,6 +31,7 @@ private:
void destroyGLContext();
void onPlatformMakeCurrent() const override;
+ std::function<void()> onPlatformGetAutoContextRestore() const override;
void onPlatformSwapBuffers() const override;
GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
@@ -113,6 +120,7 @@ WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext*
glrc = fPbufferContext->getGLRC();
}
+ SkScopeExit restorer(context_restorer());
if (!(wglMakeCurrent(dc, glrc))) {
SkDebugf("Could not set the context.\n");
this->destroyGLContext();
@@ -142,6 +150,7 @@ WinGLTestContext::~WinGLTestContext() {
void WinGLTestContext::destroyGLContext() {
SkSafeSetNull(fPbufferContext);
if (fGlRenderContext) {
+ // This deletes the context immediately even if it is current.
wglDeleteContext(fGlRenderContext);
fGlRenderContext = 0;
}
@@ -172,6 +181,13 @@ void WinGLTestContext::onPlatformMakeCurrent() const {
}
}
+std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
+ if (wglGetCurrentContext() == fGlRenderContext) {
+ return nullptr;
+ }
+ return context_restorer();
+}
+
void WinGLTestContext::onPlatformSwapBuffers() const {
HDC dc;
diff --git a/chromium/third_party/skia/tools/gpu/mock/MockTestContext.cpp b/chromium/third_party/skia/tools/gpu/mock/MockTestContext.cpp
index 68941ad4ef0..5cc5529dfe6 100644
--- a/chromium/third_party/skia/tools/gpu/mock/MockTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/mock/MockTestContext.cpp
@@ -34,6 +34,7 @@ public:
protected:
void teardown() override {}
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
private:
diff --git a/chromium/third_party/skia/tools/gpu/mtl/MtlTestContext.mm b/chromium/third_party/skia/tools/gpu/mtl/MtlTestContext.mm
index 4014e2ba706..38755b2ef0f 100644
--- a/chromium/third_party/skia/tools/gpu/mtl/MtlTestContext.mm
+++ b/chromium/third_party/skia/tools/gpu/mtl/MtlTestContext.mm
@@ -144,6 +144,7 @@ private:
}
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
id<MTLDevice> fDevice;
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkTestContext.cpp b/chromium/third_party/skia/tools/gpu/vk/VkTestContext.cpp
index e329583a037..fa40c7374a7 100644
--- a/chromium/third_party/skia/tools/gpu/vk/VkTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/vk/VkTestContext.cpp
@@ -10,9 +10,9 @@
#ifdef SK_VULKAN
#include "GrContext.h"
+#include "VkTestUtils.h"
#include "vk/GrVkInterface.h"
#include "vk/GrVkUtil.h"
-#include <vulkan/vulkan.h>
namespace {
/**
@@ -114,8 +114,12 @@ public:
if (sharedContext) {
backendContext = sharedContext->getVkBackendContext();
} else {
- backendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr,
- vkGetDeviceProcAddr));
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+ backendContext.reset(GrVkBackendContext::Create(instProc, devProc));
}
if (!backendContext) {
return nullptr;
@@ -150,6 +154,7 @@ private:
}
void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
void onPlatformSwapBuffers() const override {}
typedef sk_gpu_test::VkTestContext INHERITED;
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp b/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
new file mode 100644
index 00000000000..3033076a4c6
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "VkTestUtils.h"
+
+#ifdef SK_VULKAN
+
+#include "../ports/SkOSLibrary.h"
+
+namespace sk_gpu_test {
+
+bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc,
+ PFN_vkGetDeviceProcAddr* devProc) {
+ static void* vkLib = nullptr;
+ static PFN_vkGetInstanceProcAddr localInstProc = nullptr;
+ static PFN_vkGetDeviceProcAddr localDevProc = nullptr;
+ if (!vkLib) {
+#if defined _WIN32
+ vkLib = DynamicLoadLibrary("vulkan-1.dll");
+#else
+ vkLib = DynamicLoadLibrary("libvulkan.so");
+#endif
+ if (!vkLib) {
+ return false;
+ }
+ localInstProc = (PFN_vkGetInstanceProcAddr) GetProcedureAddress(vkLib,
+ "vkGetInstanceProcAddr");
+ localDevProc = (PFN_vkGetDeviceProcAddr) GetProcedureAddress(vkLib,
+ "vkGetDeviceProcAddr");
+ }
+ if (!localInstProc || !localDevProc) {
+ return false;
+ }
+ *instProc = localInstProc;
+ *devProc = localDevProc;
+ return true;
+}
+}
+
+#endif
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.h b/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.h
new file mode 100644
index 00000000000..9f34ef09c58
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef VkTestUtils_DEFINED
+#define VkTestUtils_DEFINED
+
+#include "SkTypes.h"
+
+#ifdef SK_VULKAN
+
+#include "vk/GrVkDefines.h"
+
+namespace sk_gpu_test {
+ bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr*, PFN_vkGetDeviceProcAddr*);
+}
+
+#endif
+#endif
+
diff --git a/chromium/third_party/skia/tools/gpucts/gm_knowledge.c b/chromium/third_party/skia/tools/gpucts/gm_knowledge.c
new file mode 100644
index 00000000000..8dbdd00f09c
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpucts/gm_knowledge.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm_knowledge.h"
+
+// placeholder function definitions:
+float GMK_Check(GMK_ImageData d, const char* n) { return 0; }
+bool GMK_IsGoodGM(const char* n) { return true; }
diff --git a/chromium/third_party/skia/tools/gpucts/gm_knowledge.h b/chromium/third_party/skia/tools/gpucts/gm_knowledge.h
new file mode 100644
index 00000000000..d9d71e05c53
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpucts/gm_knowledge.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef gm_knowledge_DEFINED
+#define gm_knowledge_DEFINED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+A structure representing an image. pix should either be nullptr (representing
+a missing image) or point to a block of memory width*height in size.
+
+Each pixel is an un-pre-multiplied RGBA color:
+ void set_color(GMK_ImageData* data, int x, int y,
+ unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ data->pix[x + data->width * y] = (r << 0) | (g << 8) | (b << 16) | (a << 24);
+ }
+ */
+typedef struct {
+ const uint32_t* pix;
+ int width;
+ int height;
+} GMK_ImageData;
+
+/**
+Check if the given test image matches the expected results.
+
+@param data the image
+@param gm_name the name of the rendering test that produced the image
+
+@return 0 if the test passes, otherwise a positive number representing how
+ badly it failed.
+ */
+float GMK_Check(GMK_ImageData data, const char* gm_name);
+
+/**
+Check to see if the given test has expected results.
+
+@param gm_name the name of a rendering test.
+
+@return true of expected results are known for the given test.
+*/
+bool GMK_IsGoodGM(const char* gm_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // gm_knowledge_DEFINED
diff --git a/chromium/third_party/skia/tools/gpucts/gm_runner.cpp b/chromium/third_party/skia/tools/gpucts/gm_runner.cpp
new file mode 100644
index 00000000000..a18c457d1bb
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpucts/gm_runner.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm_runner.h"
+
+#include <algorithm>
+
+#include "SkSurface.h"
+#include "gm.h"
+
+#if SK_SUPPORT_GPU
+
+#include "GrContextFactory.h"
+
+using sk_gpu_test::GrContextFactory;
+
+namespace gm_runner {
+
+static GrContextFactory::ContextType to_context_type(SkiaBackend backend) {
+ switch (backend) {
+ case SkiaBackend::kGL: return GrContextFactory::kGL_ContextType;
+ case SkiaBackend::kGLES: return GrContextFactory::kGLES_ContextType;
+ case SkiaBackend::kVulkan: return GrContextFactory::kVulkan_ContextType;
+ }
+ SkDEBUGFAIL(""); return (GrContextFactory::ContextType)0;
+}
+
+const char* GetBackendName(SkiaBackend backend) {
+ return GrContextFactory::ContextTypeName(to_context_type(backend));
+}
+
+bool BackendSupported(SkiaBackend backend) {
+ GrContextFactory factory;
+ return factory.get(to_context_type(backend)) != nullptr;
+}
+
+
+GMK_ImageData Evaluate(SkiaBackend backend,
+ GMFactory gmFact,
+ std::vector<uint32_t>* storage) {
+ SkASSERT(gmFact);
+ SkASSERT(storage);
+ std::unique_ptr<skiagm::GM> gm(gmFact(nullptr));
+ SkASSERT(gm.get());
+ int w = SkScalarRoundToInt(gm->width());
+ int h = SkScalarRoundToInt(gm->height());
+ GrContextFactory contextFactory;
+ GrContext* context = contextFactory.get(to_context_type(backend));
+ if (!context) {
+ return GMK_ImageData{nullptr, w, h};
+ }
+ SkASSERT(context);
+ constexpr SkColorType ct = kRGBA_8888_SkColorType;
+
+ sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(
+ context, SkBudgeted::kNo, SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType));
+ if (!s) {
+ return GMK_ImageData{nullptr, w, h};
+ }
+ gm->draw(s->getCanvas());
+
+ storage->resize(w * h);
+ uint32_t* pix = storage->data();
+ SkASSERT(SkColorTypeBytesPerPixel(ct) == sizeof(uint32_t));
+ SkAssertResult(s->readPixels(SkImageInfo::Make(w, h, ct, kUnpremul_SkAlphaType),
+ pix, w * sizeof(uint32_t), 0, 0));
+ return GMK_ImageData{pix, w, h};
+}
+
+} // namespace gm_runner
+
+#else
+namespace sk_gpu_test {
+ class GrContextFactory {};
+}
+namespace gm_runner {
+bool BackendSupported(SkiaBackend) { return false; }
+GMK_ImageData Evaluate(SkiaBackend, GMFactory, std::vector<uint32_t>*) {
+ return GMK_ImageData{nullptr, 0, 0};
+}
+const char* GetBackendName(SkiaBackend backend) { return "Unknown"; }
+} // namespace gm_runner
+#endif
+
+namespace gm_runner {
+
+std::vector<GMFactory> GetGMFactories() {
+ std::vector<GMFactory> result;
+ for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
+ result.push_back(r->factory());
+ }
+ struct {
+ bool operator()(GMFactory u, GMFactory v) const { return GetGMName(u) < GetGMName(v); }
+ } less;
+ std::sort(result.begin(), result.end(), less);
+ return result;
+}
+
+std::string GetGMName(GMFactory gmFactory) {
+ SkASSERT(gmFactory);
+ std::unique_ptr<skiagm::GM> gm(gmFactory(nullptr));
+ SkASSERT(gm);
+ return std::string(gm->getName());
+}
+} // namespace gm_runner
diff --git a/chromium/third_party/skia/tools/gpucts/gm_runner.h b/chromium/third_party/skia/tools/gpucts/gm_runner.h
new file mode 100644
index 00000000000..cd0d7d32bb0
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpucts/gm_runner.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef gm_runner_DEFINED
+#define gm_runner_DEFINED
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "gm_knowledge.h"
+
+/**
+A Skia GM is a single rendering test that can be executed on any Skia backend Canvas.
+*/
+namespace skiagm {
+ class GM;
+}
+
+namespace sk_gpu_test {
+ class GrContextFactory;
+}
+
+namespace gm_runner {
+
+using GMFactory = skiagm::GM* (*)(void*);
+
+enum class SkiaBackend {
+ kGL,
+ kGLES,
+ kVulkan,
+};
+
+bool BackendSupported(SkiaBackend);
+
+/**
+@return a list of all Skia GMs in lexicographic order.
+*/
+std::vector<GMFactory> GetGMFactories();
+
+/**
+@return a descriptive name for the GM.
+*/
+std::string GetGMName(GMFactory);
+/**
+@return a descriptive name for the backend.
+*/
+const char* GetBackendName(SkiaBackend);
+
+/**
+Execute the given GM on the given Skia backend. Then copy the pixels into the
+storage (overwriting existing contents of storage).
+
+@return the rendered image. Return a null ImageData on error.
+*/
+GMK_ImageData Evaluate(SkiaBackend,
+ GMFactory,
+ std::vector<uint32_t>* storage);
+
+} // namespace gm_runner
+
+#endif // gm_runner_DEFINED
diff --git a/chromium/third_party/skia/tools/gpucts/gpucts.cpp b/chromium/third_party/skia/tools/gpucts/gpucts.cpp
new file mode 100644
index 00000000000..c50519cc5be
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpucts/gpucts.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkGraphics.h"
+#include "gm_runner.h"
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wused-but-marked-unused"
+#endif
+
+#include "gtest/gtest.h"
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#include "Test.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct GMTestCase {
+ gm_runner::GMFactory fGMFactory;
+ gm_runner::SkiaBackend fBackend;
+};
+
+struct GMTest : public testing::Test {
+ GMTestCase fTest;
+ GMTest(GMTestCase t) : fTest(t) {}
+ void TestBody() override {
+ if (!fTest.fGMFactory) {
+ EXPECT_TRUE(gm_runner::BackendSupported(fTest.fBackend));
+ return;
+ }
+ std::vector<uint32_t> pixels;
+ GMK_ImageData imgData = gm_runner::Evaluate(fTest.fBackend, fTest.fGMFactory, &pixels);
+ EXPECT_TRUE(imgData.pix);
+ if (!imgData.pix) {
+ return;
+ }
+ std::string gmName = gm_runner::GetGMName(fTest.fGMFactory);
+ float result = GMK_Check(imgData, gmName.c_str());
+ EXPECT_EQ(result, 0);
+ }
+};
+
+struct GMTestFactory : public testing::internal::TestFactoryBase {
+ GMTestCase fTest;
+ GMTestFactory(GMTestCase t) : fTest(t) {}
+ testing::Test* CreateTest() override { return new GMTest(fTest); }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#if !SK_SUPPORT_GPU
+struct GrContextOptions {};
+#endif
+
+struct UnitTest : public testing::Test {
+ skiatest::TestProc fProc;
+ UnitTest(skiatest::TestProc proc) : fProc(proc) {}
+ void TestBody() override {
+ struct : skiatest::Reporter {
+ void reportFailed(const skiatest::Failure& failure) override {
+ SkString desc = failure.toString();
+ SK_ABORT("");
+ GTEST_NONFATAL_FAILURE_(desc.c_str());
+ }
+ } r;
+ fProc(&r, GrContextOptions());
+ }
+};
+
+struct UnitTestFactory : testing::internal::TestFactoryBase {
+ skiatest::TestProc fProc;
+ UnitTestFactory(skiatest::TestProc proc) : fProc(proc) {}
+ testing::Test* CreateTest() override { return new UnitTest(fProc); }
+};
+
+std::vector<const skiatest::Test*> GetUnitTests() {
+ // Unit Tests
+ std::vector<const skiatest::Test*> tests;
+ for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
+ tests.push_back(&r->factory());
+ }
+ struct {
+ bool operator()(const skiatest::Test* u, const skiatest::Test* v) const {
+ return strcmp(u->name, v->name) < 0;
+ }
+ } less;
+ std::sort(tests.begin(), tests.end(), less);
+ return tests;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static void reg_test(const char* test, const char* testCase,
+ testing::internal::TestFactoryBase* fact) {
+ testing::internal::MakeAndRegisterTestInfo(
+ test,
+ testCase,
+ nullptr,
+ nullptr,
+ testing::internal::CodeLocation(__FILE__, __LINE__),
+ testing::internal::GetTestTypeId(),
+ testing::Test::SetUpTestCase,
+ testing::Test::TearDownTestCase,
+ fact);
+}
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ SkGraphics::Init();
+
+ // Rendering Tests
+ gm_runner::SkiaBackend backends[] = {
+ #ifndef SK_BUILD_FOR_ANDROID
+ gm_runner::SkiaBackend::kGL, // Used for testing on desktop machines.
+ #endif
+ gm_runner::SkiaBackend::kGLES,
+ gm_runner::SkiaBackend::kVulkan,
+ };
+ std::vector<gm_runner::GMFactory> gms = gm_runner::GetGMFactories();
+ for (auto backend : backends) {
+ const char* backendName = GetBackendName(backend);
+ std::string test = std::string("SkiaGM_") + backendName;
+ reg_test(test.c_str(), "BackendSupported", new GMTestFactory(GMTestCase{nullptr, backend}));
+
+ if (!gm_runner::BackendSupported(backend)) {
+ continue;
+ }
+ for (auto gmFactory : gms) {
+ std::string gmName = gm_runner::GetGMName(gmFactory);
+ if (!GMK_IsGoodGM(gmName.c_str())) {
+ continue;
+ }
+ #ifdef SK_DEBUG
+ // The following test asserts on my phone.
+ // TODO(halcanary): fix this.
+ if(gmName == std::string("complexclip3_simple") &&
+ backend == gm_runner::SkiaBackend::kGLES) {
+ continue;
+ }
+ #endif
+ reg_test(test.c_str(), gmName.c_str(),
+ new GMTestFactory(GMTestCase{gmFactory, backend}));
+ }
+ }
+
+ for (const skiatest::Test* test : GetUnitTests()) {
+ reg_test("Skia_Unit_Tests", test->name, new UnitTestFactory(test->proc));
+ }
+ return RUN_ALL_TESTS();
+}
+
diff --git a/chromium/third_party/skia/tools/iOSShell.cpp b/chromium/third_party/skia/tools/iOSShell.cpp
deleted file mode 100644
index 2e4f0fdb5e3..00000000000
--- a/chromium/third_party/skia/tools/iOSShell.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "iOSShell.h"
-
-#include "Resources.h"
-#include "SkApplication.h"
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkGraphics.h"
-#include "SkWindow.h"
-#include "sk_tool_utils.h"
-
-//////////////////////////////////////////////////////////////////////////////
-
-static SkView* curr_view(SkWindow* wind) {
- SkView::F2BIter iter(wind);
- return iter.next();
-}
-
-ShellWindow::ShellWindow(void* hwnd, int argc, char** argv)
- : INHERITED(hwnd) {
- SkCommandLineFlags::Parse(argc, argv);
-}
-
-ShellWindow::~ShellWindow() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-bool ShellWindow::onDispatchClick(int x, int y, Click::State state,
- void* owner, unsigned modi) {
- int w = SkScalarRoundToInt(this->width());
- int h = SkScalarRoundToInt(this->height());
-
- // check for the resize-box
- if (w - x < 16 && h - y < 16) {
- return false; // let the OS handle the click
- } else {
- return this->INHERITED::onDispatchClick(x, y, state, owner, modi);
- }
-}
-
-void ShellWindow::onSizeChange() {
- this->INHERITED::onSizeChange();
-
- SkView::F2BIter iter(this);
- SkView* view = iter.next();
- view->setSize(this->width(), this->height());
-}
-
-DEFINE_bool(dm, false, "run dm");
-DEFINE_bool(nanobench, false, "run nanobench");
-
-int nanobench_main();
-int dm_main();
-
-IOS_launch_type set_cmd_line_args(int argc, char *argv[], const char* resourceDir) {
- SkCommandLineFlags::Parse(argc, argv);
- if (FLAGS_nanobench) {
- return nanobench_main() ? kError_iOSLaunchType : kTool_iOSLaunchType;
- }
- if (FLAGS_dm) {
- return dm_main() ? kError_iOSLaunchType : kTool_iOSLaunchType;
- }
- return kError_iOSLaunchType;
-}
-
-// FIXME: this should be in a header
-SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv);
-SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
- return new ShellWindow(hwnd, argc, argv);
-}
-
-// FIXME: this should be in a header
-void application_init();
-void application_init() {
- SkGraphics::Init();
- SkEvent::Init();
-}
-
-// FIXME: this should be in a header
-void application_term();
-void application_term() {
- SkEvent::Term();
-}
diff --git a/chromium/third_party/skia/tools/iOSShell.h b/chromium/third_party/skia/tools/iOSShell.h
deleted file mode 100644
index eaecba5e0b4..00000000000
--- a/chromium/third_party/skia/tools/iOSShell.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2014 Skia
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef iOSShell_DEFINED
-#define iOSShell_DEFINED
-
-#include "SkWindow.h"
-
-class SkCanvas;
-class SkEvent;
-class SkViewFactory;
-
-class ShellWindow : public SkOSWindow {
-public:
- ShellWindow(void* hwnd, int argc, char** argv);
- virtual ~ShellWindow();
-
-protected:
- void onSizeChange() override;
-
- virtual bool onDispatchClick(int x, int y, Click::State, void* owner,
- unsigned modi) override;
-
-private:
- typedef SkOSWindow INHERITED;
-};
-
-#endif
diff --git a/chromium/third_party/skia/tools/install_dependencies.sh b/chromium/third_party/skia/tools/install_dependencies.sh
index fd5c3669d0c..9d1a45fa157 100755
--- a/chromium/third_party/skia/tools/install_dependencies.sh
+++ b/chromium/third_party/skia/tools/install_dependencies.sh
@@ -31,7 +31,6 @@ if command -v lsb_release > /dev/null ; then
libfreetype6-dev
libgif-dev
libglu1-mesa-dev
- libosmesa6-dev
libpng12-dev
libqt4-dev
EOF
diff --git a/chromium/third_party/skia/tools/mirror-dev.sh b/chromium/third_party/skia/tools/mirror-dev.sh
index eb948f44174..47786de2bcc 100755
--- a/chromium/third_party/skia/tools/mirror-dev.sh
+++ b/chromium/third_party/skia/tools/mirror-dev.sh
@@ -3,7 +3,7 @@
# found in the LICENSE file.
# For each installed *-dev package DEV
- for DEV in $(dpkg --list | grep '^ii [^ ]' | cut -d ' ' -f 3 | grep '\-dev$')
+ for DEV in $(dpkg --list | grep '^ii [^ ]' | cut -d ' ' -f 3 | grep -P '\-dev($|\:amd64$)')
do
# For each multi-arch *.so SO installed by DEV
for DEV_64_SO in $(dpkg -L $DEV | grep '/lib/x86_64-linux-gnu/.*\.so$')
diff --git a/chromium/third_party/skia/tools/ok_test.cpp b/chromium/third_party/skia/tools/ok_test.cpp
index 7c020d88e1d..232904209d4 100644
--- a/chromium/third_party/skia/tools/ok_test.cpp
+++ b/chromium/third_party/skia/tools/ok_test.cpp
@@ -10,6 +10,8 @@
#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
+#else
+struct GrContextOptions {};
#endif
struct TestStream : Stream {
@@ -46,14 +48,8 @@ struct TestStream : Stream {
reporter.extended = extended;
reporter.verbose_ = verbose;
- sk_gpu_test::GrContextFactory* factory = nullptr;
- #if SK_SUPPORT_GPU
GrContextOptions options;
- sk_gpu_test::GrContextFactory a_real_factory(options);
- factory = &a_real_factory;
- #endif
-
- test.run(&reporter, factory);
+ test.run(&reporter, options);
return reporter.status;
}
};
@@ -95,7 +91,7 @@ namespace skiatest {
#endif
void RunWithGPUTestContexts(GrContextTestFn* test, GrContextTypeFilterFn* contextTypeFilter,
- Reporter* reporter, sk_gpu_test::GrContextFactory* factory) {
+ Reporter* reporter, const GrContextOptions& options) {
// TODO(bsalomon)
}
}
diff --git a/chromium/third_party/skia/tools/ok_vias.cpp b/chromium/third_party/skia/tools/ok_vias.cpp
index 815b159a01e..7c246644eef 100644
--- a/chromium/third_party/skia/tools/ok_vias.cpp
+++ b/chromium/third_party/skia/tools/ok_vias.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "../dm/DMFontMgr.h"
#include "ProcStats.h"
#include "SkColorFilter.h"
#include "SkEventTracingPriv.h"
@@ -266,7 +267,6 @@ struct Memory : Dst {
};
static Register memory{"memory", "print process maximum memory usage", Memory::Create};
-static SkOnce init_tracing_once;
struct Trace : Dst {
std::unique_ptr<Dst> target;
std::string trace_mode;
@@ -279,7 +279,8 @@ struct Trace : Dst {
}
Status draw(Src* src) override {
- init_tracing_once([&] { initializeEventTracingForTools(trace_mode.c_str()); });
+ static SkOnce once;
+ once([&] { initializeEventTracingForTools(trace_mode.c_str()); });
return target->draw(src);
}
@@ -287,6 +288,31 @@ struct Trace : Dst {
return target->image();
}
};
-static Register trace {"trace",
- "enable tracing in mode=atrace, mode=debugf, or mode=trace.json",
- Trace::Create};
+static Register trace{"trace",
+ "enable tracing in mode=atrace, mode=debugf, or mode=trace.json",
+ Trace::Create};
+
+extern sk_sp<SkFontMgr> (*gSkFontMgr_DefaultFactory)();
+
+struct PortableFonts : Dst {
+ std::unique_ptr<Dst> target;
+
+ static std::unique_ptr<Dst> Create(Options options, std::unique_ptr<Dst> dst) {
+ PortableFonts via;
+ via.target = std::move(dst);
+ return move_unique(via);
+ }
+
+ Status draw(Src* src) override {
+ static SkOnce once;
+ once([]{ gSkFontMgr_DefaultFactory = &DM::MakeFontMgr; });
+ return target->draw(src);
+ }
+
+ sk_sp<SkImage> image() override {
+ return target->image();
+ }
+};
+static Register portable_fonts{"portable_fonts",
+ "use DM::FontMgr to make fonts more portable",
+ PortableFonts::Create};
diff --git a/chromium/third_party/skia/tools/rebaseline/toggle_legacy_flag.py b/chromium/third_party/skia/tools/rebaseline/toggle_legacy_flag.py
new file mode 100644
index 00000000000..80edeb2bc46
--- /dev/null
+++ b/chromium/third_party/skia/tools/rebaseline/toggle_legacy_flag.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+README = """
+Automatically add or remove a specific legacy flag to multiple Skia client repos.
+
+This would only work on Google desktop.
+
+Example usage:
+ $ python toggle_legacy_flag.py SK_SUPPORT_LEGACY_SOMETHING \\
+ -a /data/android -c ~/chromium/src -g legacyflag
+
+If you only need to add the flag to one repo, for example, Android, please give
+only -a (--android-dir) argument:
+ $ python toggle_legacy_flag.py SK_SUPPORT_LEGACY_SOMETHING -a /data/android
+
+"""
+
+import os, sys
+import argparse
+import subprocess
+import getpass
+from random import randint
+
+
+ANDROID_TOOLS_DIR = os.path.join(
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
+ 'android')
+
+
+def toggle_android(args):
+ sys.path.append(ANDROID_TOOLS_DIR)
+ import upload_to_android
+
+ modifier = upload_to_android.AndroidLegacyFlagModifier(args.flag)
+ upload_to_android.upload_to_android(args.android_dir, modifier)
+
+
+def toggle_chromium(args):
+ os.chdir(args.chromium_dir)
+
+ branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])
+ branch = branch.strip()
+
+ EXPECTED_STASH_OUT = "No local changes to save"
+ stash_output = subprocess.check_output(['git', 'stash']).strip()
+
+ if branch != "master" or stash_output != EXPECTED_STASH_OUT:
+ print ("Please checkout a clean master branch at your chromium repo (%s) "
+ "before running this script") % args.chromium_dir
+ if stash_output != EXPECTED_STASH_OUT:
+ subprocess.check_call(['git', 'stash', 'pop'])
+ exit(1)
+
+ # Update the repository to avoid conflicts
+ subprocess.check_call(['git', 'pull'])
+ subprocess.check_call(['gclient', 'sync']);
+
+ # Use random number to avoid branch name collision.
+ # We'll delete the branch in the end.
+ random = randint(1, 10000)
+ subprocess.check_call(['git', 'checkout', '-b', 'legacyflag_%d' % random])
+
+ try:
+ config_file = os.path.join('skia', 'config', 'SkUserConfig.h')
+ with open(config_file) as f:
+ lines = f.readlines()
+
+ flag_line = "#define %s\n" % args.flag
+ if flag_line in lines:
+ index = lines.index(flag_line)
+ del lines[index-1 : index +2]
+ verb = "Remove"
+ else:
+ separator = (
+ "/////////////////////////"
+ " Imported from BUILD.gn and skia_common.gypi\n")
+ content = ("#ifndef {0}\n"
+ "#define {0}\n"
+ "#endif\n\n").format(args.flag)
+ lines.insert(lines.index(separator), content)
+ verb = "Add"
+
+ with open(config_file, 'w') as f:
+ for line in lines:
+ f.write(line)
+
+ message = "%s %s" % (verb, args.flag)
+
+ subprocess.check_call('git commit -a -m "%s"' % message, shell=True)
+ subprocess.check_call('git cl upload -m "%s" -f' % message,
+ shell=True)
+ finally:
+ subprocess.check_call(['git', 'checkout', 'master'])
+ subprocess.check_call(['git', 'branch', '-D', 'legacyflag_%d' % random])
+
+
+def toggle_google3(args):
+ G3_SCRIPT_DIR = os.path.expanduser("~/skia-g3/scripts")
+ if not os.path.isdir(G3_SCRIPT_DIR):
+ print ("Google3 directory unavailable.\n"
+ "Please see "
+ "https://sites.google.com/a/google.com/skia/rebaseline#g3_flag "
+ "for Google3 setup.")
+ exit(1)
+ sys.path.append(G3_SCRIPT_DIR)
+ import citc_flag
+
+ citc_flag.toggle_google3(args.google3, args.flag)
+
+
+def main():
+ if len(sys.argv) <= 1 or sys.argv[1] == '-h' or sys.argv[1] == '--help':
+ print README
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--android-dir', '-a', required=False,
+ help='Directory where an Android checkout will be created (if it does '
+ 'not already exist). Note: ~1GB space will be used.')
+ parser.add_argument(
+ '--chromium-dir', '-c', required=False,
+ help='Directory of an EXISTING Chromium checkout (e.g., ~/chromium/src)')
+ parser.add_argument(
+ '--google3', '-g', required=False,
+ help='Google3 workspace to be created (if it does not already exist).')
+ parser.add_argument('flag', type=str, help='legacy flag name')
+
+ args = parser.parse_args()
+
+ if not args.android_dir and not args.chromium_dir and not args.google3:
+ print """
+Nothing to do. Please give me at least one of these three arguments:
+ -a (--android-dir)
+ -c (--chromium-dir)
+ -g (--google3)
+"""
+ exit(1)
+
+ end_message = "CLs generated. Now go review and land them:\n"
+ if args.chromium_dir:
+ args.chromium_dir = os.path.expanduser(args.chromium_dir)
+ toggle_chromium(args)
+ end_message += " * https://chromium-review.googlesource.com\n"
+ if args.google3:
+ toggle_google3(args)
+ end_message += " * http://goto.google.com/cl\n"
+ if args.android_dir:
+ args.android_dir = os.path.expanduser(args.android_dir)
+ toggle_android(args)
+ end_message += " * http://goto.google.com/androidcl\n"
+
+ print end_message
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/Application.h b/chromium/third_party/skia/tools/sk_app/Application.h
index df9a20d3583..df9a20d3583 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/Application.h
+++ b/chromium/third_party/skia/tools/sk_app/Application.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/CommandSet.cpp b/chromium/third_party/skia/tools/sk_app/CommandSet.cpp
index d0154d6e617..d0154d6e617 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/CommandSet.cpp
+++ b/chromium/third_party/skia/tools/sk_app/CommandSet.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/CommandSet.h b/chromium/third_party/skia/tools/sk_app/CommandSet.h
index 0784a3875e8..0784a3875e8 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/CommandSet.h
+++ b/chromium/third_party/skia/tools/sk_app/CommandSet.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/DisplayParams.h b/chromium/third_party/skia/tools/sk_app/DisplayParams.h
index 959735e8ff2..959735e8ff2 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/DisplayParams.h
+++ b/chromium/third_party/skia/tools/sk_app/DisplayParams.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/GLWindowContext.cpp b/chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp
index bdfa12a8eca..bdfa12a8eca 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/GLWindowContext.cpp
+++ b/chromium/third_party/skia/tools/sk_app/GLWindowContext.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/GLWindowContext.h b/chromium/third_party/skia/tools/sk_app/GLWindowContext.h
index 44810c93d23..44810c93d23 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/GLWindowContext.h
+++ b/chromium/third_party/skia/tools/sk_app/GLWindowContext.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/RasterWindowContext.h b/chromium/third_party/skia/tools/sk_app/RasterWindowContext.h
index 75bde03ad71..75bde03ad71 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/RasterWindowContext.h
+++ b/chromium/third_party/skia/tools/sk_app/RasterWindowContext.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.cpp b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
index a9124d5e413..5e0f12412e3 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.cpp
+++ b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
@@ -22,14 +22,16 @@
#undef CreateSemaphore
#endif
-#define GET_PROC(F) f ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
-#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
+#define GET_PROC(F) f ## F = (PFN_vk ## F) fGetInstanceProcAddr(instance, "vk" #F)
+#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) fGetDeviceProcAddr(device, "vk" #F)
namespace sk_app {
VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
CreateVkSurfaceFn createVkSurface,
- CanPresentFn canPresent)
+ CanPresentFn canPresent,
+ PFN_vkGetInstanceProcAddr instProc,
+ PFN_vkGetDeviceProcAddr devProc)
: WindowContext(params)
, fCreateVkSurfaceFn(createVkSurface)
, fCanPresentFn(canPresent)
@@ -40,12 +42,14 @@ VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
, fSurfaces(nullptr)
, fCommandPool(VK_NULL_HANDLE)
, fBackbuffers(nullptr) {
+ fGetInstanceProcAddr = instProc;
+ fGetDeviceProcAddr = devProc;
this->initializeContext();
}
void VulkanWindowContext::initializeContext() {
// any config code here (particularly for msaa)?
- fBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr,
+ fBackendContext.reset(GrVkBackendContext::Create(fGetInstanceProcAddr, fGetDeviceProcAddr,
&fPresentQueueIndex, fCanPresentFn));
if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
@@ -66,6 +70,7 @@ void VulkanWindowContext::initializeContext() {
GET_DEV_PROC(GetSwapchainImagesKHR);
GET_DEV_PROC(AcquireNextImageKHR);
GET_DEV_PROC(QueuePresentKHR);
+ GET_DEV_PROC(GetDeviceQueue);
fContext = GrContext::MakeVulkan(fBackendContext.get(), fDisplayParams.fGrContextOptions);
@@ -90,7 +95,7 @@ void VulkanWindowContext::initializeContext() {
}
// create presentQueue
- vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
+ fGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
}
bool VulkanWindowContext::createSwapchain(int width, int height,
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.h b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h
index 81e5f3d2d5b..d02b11428e1 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/VulkanWindowContext.h
+++ b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h
@@ -47,7 +47,8 @@ public:
/** Platform specific function that determines whether presentation will succeed. */
using CanPresentFn = GrVkBackendContext::CanPresentFn;
- VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn);
+ VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn,
+ PFN_vkGetInstanceProcAddr, PFN_vkGetDeviceProcAddr);
private:
void initializeContext();
@@ -82,6 +83,10 @@ private:
CreateVkSurfaceFn fCreateVkSurfaceFn;
CanPresentFn fCanPresentFn;
+ // Vulkan GetProcAddr functions
+ VkPtr<PFN_vkGetInstanceProcAddr> fGetInstanceProcAddr;
+ VkPtr<PFN_vkGetDeviceProcAddr> fGetDeviceProcAddr;
+
// WSI interface functions
VkPtr<PFN_vkDestroySurfaceKHR> fDestroySurfaceKHR;
VkPtr<PFN_vkGetPhysicalDeviceSurfaceSupportKHR> fGetPhysicalDeviceSurfaceSupportKHR;
@@ -94,7 +99,7 @@ private:
VkPtr<PFN_vkGetSwapchainImagesKHR> fGetSwapchainImagesKHR;
VkPtr<PFN_vkAcquireNextImageKHR> fAcquireNextImageKHR;
VkPtr<PFN_vkQueuePresentKHR> fQueuePresentKHR;
- VkPtr<PFN_vkCreateSharedSwapchainsKHR> fCreateSharedSwapchainsKHR;
+ VkPtr<PFN_vkGetDeviceQueue> fGetDeviceQueue;
VkSurfaceKHR fSurface;
VkSwapchainKHR fSwapchain;
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/Window.cpp b/chromium/third_party/skia/tools/sk_app/Window.cpp
index d7904fd8a77..d7904fd8a77 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/Window.cpp
+++ b/chromium/third_party/skia/tools/sk_app/Window.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/Window.h b/chromium/third_party/skia/tools/sk_app/Window.h
index 73578605126..4d407809645 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/Window.h
+++ b/chromium/third_party/skia/tools/sk_app/Window.h
@@ -12,7 +12,6 @@
#include "SkRect.h"
#include "SkTouchGesture.h"
#include "SkTypes.h"
-#include "SkJSONCPP.h"
class GrContext;
class SkCanvas;
@@ -30,7 +29,9 @@ public:
virtual void setTitle(const char*) = 0;
virtual void show() = 0;
- virtual void setUIState(const Json::Value& state) {} // do nothing in default
+
+ // JSON-formatted UI state for Android. Do nothing by default
+ virtual void setUIState(const char*) {}
// Shedules an invalidation event for window if one is not currently pending.
// Make sure that either onPaint or markInvalReceived is called when the client window consumes
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/WindowContext.h b/chromium/third_party/skia/tools/sk_app/WindowContext.h
index cd4c357e207..cd4c357e207 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/WindowContext.h
+++ b/chromium/third_party/skia/tools/sk_app/WindowContext.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/GLWindowContext_android.cpp b/chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
index 944865909b5..944865909b5 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/GLWindowContext_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/GLWindowContext_android.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/RasterWindowContext_android.cpp b/chromium/third_party/skia/tools/sk_app/android/RasterWindowContext_android.cpp
index 101e51ef425..101e51ef425 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/RasterWindowContext_android.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp b/chromium/third_party/skia/tools/sk_app/android/VulkanWindowContext_android.cpp
index b50e152291b..a7d8aa7ea1a 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/VulkanWindowContext_android.cpp
@@ -9,15 +9,22 @@
#include "WindowContextFactory_android.h"
#include "../VulkanWindowContext.h"
+#include "vk/VkTestUtils.h"
+
namespace sk_app {
namespace window_context_factory {
WindowContext* NewVulkanForAndroid(ANativeWindow* window, const DisplayParams& params) {
- auto createVkSurface = [window] (VkInstance instance) -> VkSurfaceKHR {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+
+ auto createVkSurface = [window, instProc] (VkInstance instance) -> VkSurfaceKHR {
PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR =
- (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(instance,
- "vkCreateAndroidSurfaceKHR");
+ (PFN_vkCreateAndroidSurfaceKHR) instProc(instance, "vkCreateAndroidSurfaceKHR");
if (!window) {
return VK_NULL_HANDLE;
@@ -38,7 +45,8 @@ WindowContext* NewVulkanForAndroid(ANativeWindow* window, const DisplayParams& p
auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
- WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent);
+ WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent,
+ instProc, devProc);
if (!ctx->isValid()) {
delete ctx;
return nullptr;
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/WindowContextFactory_android.h b/chromium/third_party/skia/tools/sk_app/android/WindowContextFactory_android.h
index 00198da8d3b..00198da8d3b 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/WindowContextFactory_android.h
+++ b/chromium/third_party/skia/tools/sk_app/android/WindowContextFactory_android.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/Window_android.cpp b/chromium/third_party/skia/tools/sk_app/android/Window_android.cpp
index 16ad430ac28..96acfc6564c 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/Window_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/Window_android.cpp
@@ -31,7 +31,7 @@ void Window_android::setTitle(const char* title) {
fSkiaAndroidApp->setTitle(title);
}
-void Window_android::setUIState(const Json::Value& state) {
+void Window_android::setUIState(const char* state) {
fSkiaAndroidApp->setUIState(state);
}
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/Window_android.h b/chromium/third_party/skia/tools/sk_app/android/Window_android.h
index 791801140e7..9e28a8075b6 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/Window_android.h
+++ b/chromium/third_party/skia/tools/sk_app/android/Window_android.h
@@ -27,7 +27,7 @@ public:
bool attach(BackendType) override;
void onInval() override;
- void setUIState(const Json::Value& state) override;
+ void setUIState(const char* state) override;
void paintIfNeeded();
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/main_android.cpp b/chromium/third_party/skia/tools/sk_app/android/main_android.cpp
index cb8db6c3b49..cb8db6c3b49 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/main_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/main_android.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.cpp b/chromium/third_party/skia/tools/sk_app/android/surface_glue_android.cpp
index 4fb6c3d9acc..9c734247dbb 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.cpp
+++ b/chromium/third_party/skia/tools/sk_app/android/surface_glue_android.cpp
@@ -71,8 +71,8 @@ void SkiaAndroidApp::setTitle(const char* title) const {
fPThreadEnv->DeleteLocalRef(titleString);
}
-void SkiaAndroidApp::setUIState(const Json::Value& state) const {
- jstring jstr = fPThreadEnv->NewStringUTF(state.toStyledString().c_str());
+void SkiaAndroidApp::setUIState(const char* state) const {
+ jstring jstr = fPThreadEnv->NewStringUTF(state);
fPThreadEnv->CallVoidMethod(fAndroidApp, fSetStateMethodID, jstr);
fPThreadEnv->DeleteLocalRef(jstr);
}
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.h b/chromium/third_party/skia/tools/sk_app/android/surface_glue_android.h
index 3bbf3af9c3c..1dd1f2854ab 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/android/surface_glue_android.h
+++ b/chromium/third_party/skia/tools/sk_app/android/surface_glue_android.h
@@ -57,7 +57,7 @@ struct SkiaAndroidApp {
// These must be called in SkiaAndroidApp's own pthread because the JNIEnv is thread sensitive
void setTitle(const char* title) const;
- void setUIState(const Json::Value& state) const;
+ void setUIState(const char* state) const;
private:
pthread_t fThread;
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/ios/GLWindowContext_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp
index 30bacf5cea3..30bacf5cea3 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/ios/GLWindowContext_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/GLWindowContext_ios.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/ios/RasterWindowContext_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp
index 08b6560510e..08b6560510e 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/ios/RasterWindowContext_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/RasterWindowContext_ios.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/ios/WindowContextFactory_ios.h b/chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
index 09999c4c83d..09999c4c83d 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/ios/WindowContextFactory_ios.h
+++ b/chromium/third_party/skia/tools/sk_app/ios/WindowContextFactory_ios.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/ios/Window_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp
index c1bdeae5fc7..c1bdeae5fc7 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/ios/Window_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/ios/Window_ios.h b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.h
index 667fa74e825..667fa74e825 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/ios/Window_ios.h
+++ b/chromium/third_party/skia/tools/sk_app/ios/Window_ios.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/ios/main_ios.cpp b/chromium/third_party/skia/tools/sk_app/ios/main_ios.cpp
index fe82c46485e..fe82c46485e 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/ios/main_ios.cpp
+++ b/chromium/third_party/skia/tools/sk_app/ios/main_ios.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp
index 7f09d545220..7f09d545220 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/GLWindowContext_mac.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp
index 409c49f218b..409c49f218b 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/mac/RasterWindowContext_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/RasterWindowContext_mac.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/mac/WindowContextFactory_mac.h b/chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
index 3adc68bbc23..3adc68bbc23 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/mac/WindowContextFactory_mac.h
+++ b/chromium/third_party/skia/tools/sk_app/mac/WindowContextFactory_mac.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/mac/Window_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp
index 8de5b104500..8de5b104500 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/mac/Window_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/mac/Window_mac.h b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.h
index aa5c8df6962..aa5c8df6962 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/mac/Window_mac.h
+++ b/chromium/third_party/skia/tools/sk_app/mac/Window_mac.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/mac/main_mac.cpp b/chromium/third_party/skia/tools/sk_app/mac/main_mac.cpp
index 6dcf5b93f76..6dcf5b93f76 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/mac/main_mac.cpp
+++ b/chromium/third_party/skia/tools/sk_app/mac/main_mac.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
index d7a43878808..d7a43878808 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/GLWindowContext_unix.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/RasterWindowContext_unix.cpp
index 6bfa6fd0be2..6bfa6fd0be2 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/RasterWindowContext_unix.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/VulkanWindowContext_unix.cpp
index b94e8edc209..b2f1ffc7630 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/VulkanWindowContext_unix.cpp
@@ -10,6 +10,8 @@
#include "vk/GrVkInterface.h"
#include "vk/GrVkUtil.h"
+#include "vk/VkTestUtils.h"
+
#include <X11/Xlib-xcb.h>
#include "WindowContextFactory_unix.h"
@@ -20,12 +22,17 @@ namespace sk_app {
namespace window_context_factory {
WindowContext* NewVulkanForXlib(const XlibWindowInfo& info, const DisplayParams& displayParams) {
- auto createVkSurface = [&info](VkInstance instance) -> VkSurfaceKHR {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+
+ auto createVkSurface = [&info, instProc](VkInstance instance) -> VkSurfaceKHR {
static PFN_vkCreateXcbSurfaceKHR createXcbSurfaceKHR = nullptr;
if (!createXcbSurfaceKHR) {
createXcbSurfaceKHR =
- (PFN_vkCreateXcbSurfaceKHR) vkGetInstanceProcAddr(instance,
- "vkCreateXcbSurfaceKHR");
+ (PFN_vkCreateXcbSurfaceKHR) instProc(instance, "vkCreateXcbSurfaceKHR");
}
VkSurfaceKHR surface;
@@ -46,15 +53,14 @@ WindowContext* NewVulkanForXlib(const XlibWindowInfo& info, const DisplayParams&
return surface;
};
- auto canPresent = [&info](VkInstance instance, VkPhysicalDevice physDev,
+ auto canPresent = [&info, instProc](VkInstance instance, VkPhysicalDevice physDev,
uint32_t queueFamilyIndex) {
static PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
getPhysicalDeviceXcbPresentationSupportKHR = nullptr;
if (!getPhysicalDeviceXcbPresentationSupportKHR) {
getPhysicalDeviceXcbPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
- vkGetInstanceProcAddr(instance,
- "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+ instProc(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
}
@@ -66,7 +72,8 @@ WindowContext* NewVulkanForXlib(const XlibWindowInfo& info, const DisplayParams&
visualID);
return (VK_FALSE != check);
};
- WindowContext* context = new VulkanWindowContext(displayParams, createVkSurface, canPresent);
+ WindowContext* context = new VulkanWindowContext(displayParams, createVkSurface, canPresent,
+ instProc, devProc);
if (!context->isValid()) {
delete context;
return nullptr;
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/WindowContextFactory_unix.h b/chromium/third_party/skia/tools/sk_app/unix/WindowContextFactory_unix.h
index e6d033b4cd6..e6d033b4cd6 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/WindowContextFactory_unix.h
+++ b/chromium/third_party/skia/tools/sk_app/unix/WindowContextFactory_unix.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/Window_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp
index f5ca5ee0736..f5ca5ee0736 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/Window_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/Window_unix.h b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.h
index b59f502eb95..b59f502eb95 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/Window_unix.h
+++ b/chromium/third_party/skia/tools/sk_app/unix/Window_unix.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/unix/main_unix.cpp b/chromium/third_party/skia/tools/sk_app/unix/main_unix.cpp
index 4d9a64d6b62..4d9a64d6b62 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/unix/main_unix.cpp
+++ b/chromium/third_party/skia/tools/sk_app/unix/main_unix.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/ANGLEWindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
index bfdff5c6f4f..bfdff5c6f4f 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/ANGLEWindowContext_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/ANGLEWindowContext_win.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/GLWindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
index 17a6b329623..17a6b329623 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/GLWindowContext_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/GLWindowContext_win.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/RasterWindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/RasterWindowContext_win.cpp
index 85bb65e674d..85bb65e674d 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/RasterWindowContext_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/RasterWindowContext_win.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/VulkanWindowContext_win.cpp
index dbb59c10f2e..16c527cba00 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/VulkanWindowContext_win.cpp
@@ -15,15 +15,23 @@
#include "vk/GrVkInterface.h"
#include "vk/GrVkUtil.h"
+#include "vk/VkTestUtils.h"
+
namespace sk_app {
namespace window_context_factory {
WindowContext* NewVulkanForWin(HWND hwnd, const DisplayParams& params) {
- auto createVkSurface = [hwnd] (VkInstance instance) -> VkSurfaceKHR {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return nullptr;
+ }
+
+ auto createVkSurface = [hwnd, instProc] (VkInstance instance) -> VkSurfaceKHR {
static PFN_vkCreateWin32SurfaceKHR createWin32SurfaceKHR = nullptr;
if (!createWin32SurfaceKHR) {
createWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
- vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
+ instProc(instance, "vkCreateWin32SurfaceKHR");
}
HINSTANCE hinstance = GetModuleHandle(0);
VkSurfaceKHR surface;
@@ -44,22 +52,22 @@ WindowContext* NewVulkanForWin(HWND hwnd, const DisplayParams& params) {
return surface;
};
- auto canPresent = [] (VkInstance instance, VkPhysicalDevice physDev,
- uint32_t queueFamilyIndex) {
+ auto canPresent = [instProc] (VkInstance instance, VkPhysicalDevice physDev,
+ uint32_t queueFamilyIndex) {
static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
getPhysicalDeviceWin32PresentationSupportKHR = nullptr;
if (!getPhysicalDeviceWin32PresentationSupportKHR) {
getPhysicalDeviceWin32PresentationSupportKHR =
(PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
- vkGetInstanceProcAddr(instance,
- "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+ instProc(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
}
VkBool32 check = getPhysicalDeviceWin32PresentationSupportKHR(physDev, queueFamilyIndex);
return (VK_FALSE != check);
};
- WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent);
+ WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent,
+ instProc, devProc);
if (!ctx->isValid()) {
delete ctx;
return nullptr;
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/WindowContextFactory_win.h b/chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
index 959b529f494..959b529f494 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/WindowContextFactory_win.h
+++ b/chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/Window_win.cpp b/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
index 10db0ec675c..10db0ec675c 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/Window_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/Window_win.h b/chromium/third_party/skia/tools/sk_app/win/Window_win.h
index 139ab874c63..139ab874c63 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/Window_win.h
+++ b/chromium/third_party/skia/tools/sk_app/win/Window_win.h
diff --git a/chromium/third_party/skia/tools/viewer/sk_app/win/main_win.cpp b/chromium/third_party/skia/tools/sk_app/win/main_win.cpp
index 4800258973f..4800258973f 100644
--- a/chromium/third_party/skia/tools/viewer/sk_app/win/main_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/main_win.cpp
diff --git a/chromium/third_party/skia/tools/sk_tool_utils.cpp b/chromium/third_party/skia/tools/sk_tool_utils.cpp
index f1968742d4e..5321513a171 100644
--- a/chromium/third_party/skia/tools/sk_tool_utils.cpp
+++ b/chromium/third_party/skia/tools/sk_tool_utils.cpp
@@ -6,7 +6,6 @@
*/
#include "sk_tool_utils.h"
-#include "sk_tool_utils_flags.h"
#include "Resources.h"
#include "SkBitmap.h"
@@ -21,146 +20,77 @@
#include "SkTestScalerContext.h"
#include "SkTextBlob.h"
-DEFINE_bool(portableFonts, false, "Use portable fonts");
-
namespace sk_tool_utils {
-/* these are the default fonts chosen by Chrome for serif, sans-serif, and monospace */
-static const char* gStandardFontNames[][3] = {
- { "Times", "Helvetica", "Courier" }, // Mac
- { "Times New Roman", "Helvetica", "Courier" }, // iOS
- { "Times New Roman", "Arial", "Courier New" }, // Win
- { "Times New Roman", "Arial", "Monospace" }, // Ubuntu
- { "serif", "sans-serif", "monospace" }, // Android
- { "Tinos", "Arimo", "Cousine" } // ChromeOS
-};
-
-const char* platform_font_name(const char* name) {
- SkString platform = major_platform_os_name();
- int index;
- if (!strcmp(name, "serif")) {
- index = 0;
- } else if (!strcmp(name, "san-serif")) {
- index = 1;
- } else if (!strcmp(name, "monospace")) {
- index = 2;
- } else {
- return name;
- }
- if (platform.equals("Mac")) {
- return gStandardFontNames[0][index];
- }
- if (platform.equals("iOS")) {
- return gStandardFontNames[1][index];
- }
- if (platform.equals("Win")) {
- return gStandardFontNames[2][index];
- }
- if (platform.equals("Ubuntu") || platform.equals("Debian")) {
- return gStandardFontNames[3][index];
- }
- if (platform.equals("Android")) {
- return gStandardFontNames[4][index];
- }
- if (platform.equals("ChromeOS")) {
- return gStandardFontNames[5][index];
- }
- return name;
-}
-
-const char* platform_os_emoji() {
- const char* osName = platform_os_name();
- if (!strcmp(osName, "Android") || !strcmp(osName, "Ubuntu") || !strcmp(osName, "Debian")) {
- return "CBDT";
- }
- if (!strncmp(osName, "Mac", 3) || !strncmp(osName, "iOS", 3)) {
- return "SBIX";
- }
- if (!strncmp(osName, "Win", 3)) {
- return "COLR";
+static const char* platform_os_name() {
+ for (int index = 0; index < FLAGS_key.count(); index += 2) {
+ if (!strcmp("os", FLAGS_key[index])) {
+ return FLAGS_key[index + 1];
+ }
}
return "";
}
sk_sp<SkTypeface> emoji_typeface() {
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "CBDT")) {
- return MakeResourceAsTypeface("/fonts/Funkster.ttf");
+#if defined(SK_BUILD_FOR_WIN)
+ sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
+ const char *colorEmojiFontName = "Segoe UI Emoji";
+ sk_sp<SkTypeface> typeface(fm->matchFamilyStyle(colorEmojiFontName, SkFontStyle()));
+ if (typeface) {
+ return typeface;
}
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "SBIX")) {
- return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle());
+ sk_sp<SkTypeface> fallback(fm->matchFamilyStyleCharacter(
+ colorEmojiFontName, SkFontStyle(), nullptr /* bcp47 */, 0 /* bcp47Count */,
+ 0x1f4b0 /* character: 💰 */));
+ if (fallback) {
+ return fallback;
}
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "COLR")) {
- sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
- const char *colorEmojiFontName = "Segoe UI Emoji";
- sk_sp<SkTypeface> typeface(fm->matchFamilyStyle(colorEmojiFontName, SkFontStyle()));
- if (typeface) {
- return typeface;
- }
- sk_sp<SkTypeface> fallback(fm->matchFamilyStyleCharacter(
- colorEmojiFontName, SkFontStyle(), nullptr /* bcp47 */, 0 /* bcp47Count */,
- 0x1f4b0 /* character: 💰 */));
- if (fallback) {
- return fallback;
- }
- // If we don't have Segoe UI Emoji and can't find a fallback, try Segoe UI Symbol.
- // Windows 7 does not have Segoe UI Emoji; Segoe UI Symbol has the (non - color) emoji.
- return SkTypeface::MakeFromName("Segoe UI Symbol", SkFontStyle());
- }
- return nullptr;
+ // If we don't have Segoe UI Emoji and can't find a fallback, try Segoe UI Symbol.
+ // Windows 7 does not have Segoe UI Emoji; Segoe UI Symbol has the (non - color) emoji.
+ return SkTypeface::MakeFromName("Segoe UI Symbol", SkFontStyle());
+
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+ return SkTypeface::MakeFromName("Apple Color Emoji", SkFontStyle());
+
+#else
+ return MakeResourceAsTypeface("/fonts/Funkster.ttf");
+
+#endif
}
const char* emoji_sample_text() {
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "CBDT")) {
- return "Hamburgefons";
- }
- if (!strcmp(sk_tool_utils::platform_os_emoji(), "SBIX") ||
- !strcmp(sk_tool_utils::platform_os_emoji(), "COLR"))
- {
- return "\xF0\x9F\x92\xB0" "\xF0\x9F\x8F\xA1" "\xF0\x9F\x8E\x85" // 💰🏡🎅
- "\xF0\x9F\x8D\xAA" "\xF0\x9F\x8D\x95" "\xF0\x9F\x9A\x80" // 🍪🍕🚀
- "\xF0\x9F\x9A\xBB" "\xF0\x9F\x92\xA9" "\xF0\x9F\x93\xB7" // 🚻💩📷
- "\xF0\x9F\x93\xA6" // 📦
- "\xF0\x9F\x87\xBA" "\xF0\x9F\x87\xB8" "\xF0\x9F\x87\xA6"; // 🇺🇸🇦
- }
- return "";
+#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+ return "\xF0\x9F\x92\xB0" "\xF0\x9F\x8F\xA1" "\xF0\x9F\x8E\x85" // 💰🏡🎅
+ "\xF0\x9F\x8D\xAA" "\xF0\x9F\x8D\x95" "\xF0\x9F\x9A\x80" // 🍪🍕🚀
+ "\xF0\x9F\x9A\xBB" "\xF0\x9F\x92\xA9" "\xF0\x9F\x93\xB7" // 🚻💩📷
+ "\xF0\x9F\x93\xA6" // 📦
+ "\xF0\x9F\x87\xBA" "\xF0\x9F\x87\xB8" "\xF0\x9F\x87\xA6"; // 🇺🇸🇦
+#else
+ return "Hamburgefons";
+#endif
}
-const char* platform_os_name() {
+static bool extra_config_contains(const char* substring) {
for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (!strcmp("os", FLAGS_key[index])) {
- return FLAGS_key[index + 1];
+ if (0 == strcmp("extra_config", FLAGS_key[index])
+ && strstr(FLAGS_key[index + 1], substring)) {
+ return true;
}
}
- // when running SampleApp or dm without a --key pair, omit the platform name
- return "";
+ return false;
}
-// omit version number in returned value
-SkString major_platform_os_name() {
- SkString name;
- for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (!strcmp("os", FLAGS_key[index])) {
- const char* platform = FLAGS_key[index + 1];
- const char* end = platform;
- while (*end && (*end < '0' || *end > '9')) {
- ++end;
- }
- name.append(platform, end - platform);
- break;
- }
+const char* platform_font_manager() {
+ if (extra_config_contains("GDI")) {
+ return "GDI";
}
- return name;
-}
-
-const char* platform_extra_config(const char* config) {
- for (int index = 0; index < FLAGS_key.count(); index += 2) {
- if (!strcmp("extra_config", FLAGS_key[index]) && !strcmp(config, FLAGS_key[index + 1])) {
- return config;
- }
+ if (extra_config_contains("NativeFonts")){
+ return platform_os_name();
}
return "";
}
+
const char* colortype_name(SkColorType ct) {
switch (ct) {
case kUnknown_SkColorType: return "Unknown";
@@ -266,6 +196,21 @@ void add_to_text_blob(SkTextBlobBuilder* builder, const char* text,
add_to_text_blob_w_len(builder, text, strlen(text), origPaint, x, y);
}
+SkPath make_star(const SkRect& bounds, int numPts, int step) {
+ SkPath path;
+ path.setFillType(SkPath::kEvenOdd_FillType);
+ path.moveTo(0,-1);
+ for (int i = 1; i < numPts; ++i) {
+ int idx = i*step;
+ SkScalar theta = idx * 2*SK_ScalarPI/numPts + SK_ScalarPI/2;
+ SkScalar x = SkScalarCos(theta);
+ SkScalar y = -SkScalarSin(theta);
+ path.lineTo(x, y);
+ }
+ path.transform(SkMatrix::MakeRectToRect(path.getBounds(), bounds, SkMatrix::kFill_ScaleToFit));
+ return path;
+}
+
#if !defined(__clang__) && defined(_MSC_VER)
// MSVC takes ~2 minutes to compile this function with optimization.
// We don't really care to wait that long for this function.
diff --git a/chromium/third_party/skia/tools/sk_tool_utils.h b/chromium/third_party/skia/tools/sk_tool_utils.h
index b1bde770ea8..abf43323c57 100644
--- a/chromium/third_party/skia/tools/sk_tool_utils.h
+++ b/chromium/third_party/skia/tools/sk_tool_utils.h
@@ -47,29 +47,9 @@ namespace sk_tool_utils {
const char* emoji_sample_text();
/**
- * If the platform supports color emoji, return the type (i.e. "CBDT", "SBIX", "").
+ * Returns a string describing the platform font manager, if we're using one, otherwise "".
*/
- const char* platform_os_emoji();
-
- /**
- * Return the platform name with the version number ("Mac10.9", "Win8", etc.) if available.
- */
- const char* platform_os_name();
-
- /**
- * Return the platform name without the version number ("Mac", "Win", etc.) if available.
- */
- SkString major_platform_os_name();
-
- /**
- * Return the platform extra config (e.g. "GDI") if available.
- */
- const char* platform_extra_config(const char* config);
-
- /**
- * Map serif, san-serif, and monospace to the platform-specific font name.
- */
- const char* platform_font_name(const char* name);
+ const char* platform_font_manager();
/**
* Sets the paint to use a platform-independent text renderer
@@ -135,6 +115,18 @@ namespace sk_tool_utils {
void add_to_text_blob(SkTextBlobBuilder* builder, const char* text,
const SkPaint& origPaint, SkScalar x, SkScalar y);
+ // Constructs a star by walking a 'numPts'-sided regular polygon with even/odd fill:
+ //
+ // moveTo(pts[0]);
+ // lineTo(pts[step % numPts]);
+ // ...
+ // lineTo(pts[(step * (N - 1)) % numPts]);
+ //
+ // numPts=5, step=2 will produce a classic five-point star.
+ //
+ // numPts and step must be co-prime.
+ SkPath make_star(const SkRect& bounds, int numPts = 5, int step = 2);
+
void make_big_path(SkPath& path);
// Return a blurred version of 'src'. This doesn't use a separable filter
diff --git a/chromium/third_party/skia/tools/sk_tool_utils_flags.h b/chromium/third_party/skia/tools/sk_tool_utils_flags.h
deleted file mode 100644
index ee15fbdee18..00000000000
--- a/chromium/third_party/skia/tools/sk_tool_utils_flags.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef sk_tool_utils_flags_DEFINED
-#define sk_tool_utils_flags_DEFINED
-
-#include "SkCommandLineFlags.h"
-
-DECLARE_bool(portableFonts);
-DECLARE_bool(resourceFonts);
-
-#endif // sk_tool_utils_flags_DEFINED
diff --git a/chromium/third_party/skia/tools/sk_tool_utils_font.cpp b/chromium/third_party/skia/tools/sk_tool_utils_font.cpp
index 4d82368520e..8b2041ad1e6 100644
--- a/chromium/third_party/skia/tools/sk_tool_utils_font.cpp
+++ b/chromium/third_party/skia/tools/sk_tool_utils_font.cpp
@@ -61,8 +61,6 @@ sk_sp<SkTypeface> create_font(const char* name, SkFontStyle style) {
font = fontData->fCachedFont;
} else {
font = sk_make_sp<SkTestFont>(*fontData);
- SkDEBUGCODE(font->fDebugName = sub->fName);
- SkDEBUGCODE(font->fDebugStyle = sub->fStyle);
fontData->fCachedFont = font;
}
}
diff --git a/chromium/third_party/skia/tools/skiaserve/Request.cpp b/chromium/third_party/skia/tools/skiaserve/Request.cpp
index 12f35968179..6a0f4df0a93 100644
--- a/chromium/third_party/skia/tools/skiaserve/Request.cpp
+++ b/chromium/third_party/skia/tools/skiaserve/Request.cpp
@@ -79,10 +79,6 @@ SkCanvas* Request::getCanvas() {
gl = factory->getContextInfo(GrContextFactory::kGLES_ContextType,
GrContextFactory::ContextOverrides::kNone).glContext();
}
- if (!gl) {
- gl = factory->getContextInfo(GrContextFactory::kMESA_ContextType,
- GrContextFactory::ContextOverrides::kNone).glContext();
- }
if (gl) {
gl->makeCurrent();
}
@@ -136,10 +132,6 @@ GrContext* Request::getContext() {
result = fContextFactory->get(GrContextFactory::kGLES_ContextType,
GrContextFactory::ContextOverrides::kNone);
}
- if (!result) {
- result = fContextFactory->get(GrContextFactory::kMESA_ContextType,
- GrContextFactory::ContextOverrides::kNone);
- }
return result;
#else
return nullptr;
diff --git a/chromium/third_party/skia/tools/skp/webpages_playback.py b/chromium/third_party/skia/tools/skp/webpages_playback.py
index 62feaa9381c..6a8562b1582 100644
--- a/chromium/third_party/skia/tools/skp/webpages_playback.py
+++ b/chromium/third_party/skia/tools/skp/webpages_playback.py
@@ -99,7 +99,7 @@ DEVICE_TO_PLATFORM_PREFIX = {
# How many times the record_wpr binary should be retried.
RETRY_RECORD_WPR_COUNT = 5
# How many times the run_benchmark binary should be retried.
-RETRY_RUN_MEASUREMENT_COUNT = 5
+RETRY_RUN_MEASUREMENT_COUNT = 3
# Location of the credentials.json file in Google Storage.
CREDENTIALS_GS_PATH = 'playback/credentials/credentials.json'
@@ -115,6 +115,11 @@ CHROMIUM_PAGE_SETS_TO_PREFIX = {
'top_25_smooth.py': 'top25desk',
}
+PAGE_SETS_TO_EXCLUSIONS = {
+ # See skbug.com/7348
+ 'key_mobile_sites_smooth.py': '"(digg|worldjournal)"',
+}
+
def remove_prefix(s, prefix):
if s.startswith(prefix):
@@ -278,7 +283,7 @@ class SkPicturePlayback(object):
# Get the webpages archive so that it can be replayed.
self._DownloadWebpagesArchive(wpr_data_file, page_set_json_name)
- run_benchmark_cmd = (
+ run_benchmark_cmd = [
'PYTHONPATH=%s:%s:$PYTHONPATH' % (page_set_dir, self._catapult_dir),
'DISPLAY=%s' % X11_DISPLAY,
'timeout', '1800',
@@ -290,28 +295,28 @@ class SkPicturePlayback(object):
'--page-set-name=%s' % page_set_basename,
'--page-set-base-dir=%s' % page_set_dir,
'--skp-outdir=%s' % TMP_SKP_DIR,
- '--also-run-disabled-tests'
- )
+ '--also-run-disabled-tests',
+ ]
+
+ exclusions = PAGE_SETS_TO_EXCLUSIONS.get(os.path.basename(page_set))
+ if exclusions:
+ run_benchmark_cmd.append('--story-filter-exclude=' + exclusions)
for _ in range(RETRY_RUN_MEASUREMENT_COUNT):
try:
print '\n\n=======Capturing SKP of %s=======\n\n' % page_set
subprocess.check_call(' '.join(run_benchmark_cmd), shell=True)
except subprocess.CalledProcessError:
- # skpicture_printer sometimes fails with AssertionError but the
- # captured SKP is still valid. This is a known issue.
- pass
-
- # Rename generated SKP files into more descriptive names.
- try:
- self._RenameSkpFiles(page_set)
- # Break out of the retry loop since there were no errors.
- break
- except Exception:
# There was a failure continue with the loop.
traceback.print_exc()
print '\n\n=======Retrying %s=======\n\n' % page_set
time.sleep(10)
+ continue
+
+ # Rename generated SKP files into more descriptive names.
+ self._RenameSkpFiles(page_set)
+ # Break out of the retry loop since there were no errors.
+ break
else:
# If we get here then run_benchmark did not succeed and thus did not
# break out of the loop.
diff --git a/chromium/third_party/skia/tools/skp_parser.cpp b/chromium/third_party/skia/tools/skp_parser.cpp
index 887c50d1825..92e1369483a 100644
--- a/chromium/third_party/skia/tools/skp_parser.cpp
+++ b/chromium/third_party/skia/tools/skp_parser.cpp
@@ -16,6 +16,24 @@
#include <io.h>
#endif
+/*
+If you execute skp_parser with one argument, it spits out a json representation
+of the skp, but that's incomplete since it's missing many binary blobs (these
+could represent images or typefaces or just anything that doesn't currently
+have a json representation). Each unique blob is labeled with a string in the
+form "data/%d". So for example:
+
+ tools/git-sync-deps
+ bin/gn gen out/debug
+ ninja -C out/debug dm skp_parser
+ out/debug/dm -m grayscale -w /tmp/dm --config skp
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp | less
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp | grep data
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp data/0 | file -
+ out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp data/0 > /tmp/data0.png
+
+"data/0" is an image that the SKP serializer has encoded as PNG.
+*/
int main(int argc, char** argv) {
if (argc < 2) {
SkDebugf("Usage:\n %s SKP_FILE [DATA_URL]\n", argv[0]);
diff --git a/chromium/third_party/skia/tools/skpbench/_adb.py b/chromium/third_party/skia/tools/skpbench/_adb.py
index 66ef623fa57..3bf61bc86b8 100644
--- a/chromium/third_party/skia/tools/skpbench/_adb.py
+++ b/chromium/third_party/skia/tools/skpbench/_adb.py
@@ -5,12 +5,13 @@
from __future__ import print_function
import re
+import time
import subprocess
import sys
class Adb:
- def __init__(self, device_serial=None, echo=False):
- self.__invocation = ['adb']
+ def __init__(self, device_serial=None, adb_binary=None, echo=False):
+ self.__invocation = [adb_binary]
if device_serial:
self.__invocation.extend(['-s', device_serial])
self.__echo = echo
@@ -44,6 +45,13 @@ class Adb:
def remount(self):
self.__invoke('remount')
+ def reboot(self):
+ self.__is_root = None
+ self.shell('reboot')
+ self.__invoke('wait-for-device')
+ while '1' != self.check('getprop sys.boot_completed').strip():
+ time.sleep(1)
+
def __echo_shell_cmd(self, cmd):
escaped = [re.sub(r'([^a-zA-Z0-9])', r'\\\1', x)
for x in cmd.strip().splitlines()]
diff --git a/chromium/third_party/skia/tools/skpbench/_adb_path.py b/chromium/third_party/skia/tools/skpbench/_adb_path.py
index 4d8bce44255..dc23fc5895b 100644
--- a/chromium/third_party/skia/tools/skpbench/_adb_path.py
+++ b/chromium/third_party/skia/tools/skpbench/_adb_path.py
@@ -9,9 +9,9 @@ import subprocess
__ADB = None
-def init(device_serial):
+def init(device_serial, adb_binary):
global __ADB
- __ADB = Adb(device_serial)
+ __ADB = Adb(device_serial, adb_binary)
def join(*pathnames):
return '/'.join(pathnames)
diff --git a/chromium/third_party/skia/tools/skpbench/_hardware.py b/chromium/third_party/skia/tools/skpbench/_hardware.py
index de8848df783..9283243c048 100644
--- a/chromium/third_party/skia/tools/skpbench/_hardware.py
+++ b/chromium/third_party/skia/tools/skpbench/_hardware.py
@@ -41,10 +41,6 @@ class Hardware:
"""Prints any info that may help improve or debug hardware monitoring."""
pass
- def sleep(self, sleeptime):
- """Puts the hardware into a resting state for a fixed amount of time."""
- time.sleep(sleeptime)
-
class HardwareException(Exception):
"""Gets thrown when certain hardware state is not what we expect.
diff --git a/chromium/third_party/skia/tools/skpbench/_hardware_android.py b/chromium/third_party/skia/tools/skpbench/_hardware_android.py
index ebaba0ab6d8..62e3ddd4207 100644
--- a/chromium/third_party/skia/tools/skpbench/_hardware_android.py
+++ b/chromium/third_party/skia/tools/skpbench/_hardware_android.py
@@ -16,10 +16,12 @@ class HardwareAndroid(Hardware):
if self._adb.root():
self._adb.remount()
- self._initial_ASLR = \
- self._adb.check('cat /proc/sys/kernel/randomize_va_space')
def __enter__(self):
+ Hardware.__enter__(self)
+ if not self._adb.is_root() and self._adb.root():
+ self._adb.remount()
+
self._adb.shell('\n'.join([
# turn on airplane mode.
'''
@@ -53,23 +55,11 @@ class HardwareAndroid(Hardware):
print("WARNING: no adb root access; results may be unreliable.",
file=sys.stderr)
- return Hardware.__enter__(self)
+ return self
def __exit__(self, exception_type, exception_value, traceback):
Hardware.__exit__(self, exception_type, exception_value, traceback)
-
- if self._adb.is_root():
- self._adb.shell('\n'.join([
- # restore ASLR.
- '''
- echo %s > /proc/sys/kernel/randomize_va_space''' % self._initial_ASLR,
-
- # revive the gui.
- '''
- setprop ctl.start drm
- setprop ctl.start surfaceflinger
- setprop ctl.start zygote
- setprop ctl.start media''']))
+ self._adb.reboot() # some devices struggle waking up; just hard reboot.
def sanity_check(self):
Hardware.sanity_check(self)
@@ -102,6 +92,3 @@ class HardwareAndroid(Hardware):
done''')
Hardware.print_debug_diagnostics(self)
-
- def sleep(self, sleeptime):
- Hardware.sleep(self, sleeptime)
diff --git a/chromium/third_party/skia/tools/skpbench/_hardware_nexus_6p.py b/chromium/third_party/skia/tools/skpbench/_hardware_nexus_6p.py
index 077933bb410..5ca63fdedab 100644
--- a/chromium/third_party/skia/tools/skpbench/_hardware_nexus_6p.py
+++ b/chromium/third_party/skia/tools/skpbench/_hardware_nexus_6p.py
@@ -14,17 +14,9 @@ class HardwareNexus6P(HardwareAndroid):
HardwareAndroid.__init__(self, adb)
def __enter__(self):
- self._lock_clocks()
- return HardwareAndroid.__enter__(self)
-
- def __exit__(self, exception_type, exception_value, exception_traceback):
- HardwareAndroid.__exit__(self, exception_type,
- exception_value, exception_traceback)
- self._unlock_clocks()
-
- def _lock_clocks(self):
+ HardwareAndroid.__enter__(self)
if not self._adb.is_root():
- return
+ return self
self._adb.shell('''\
stop thermal-engine
@@ -72,51 +64,7 @@ class HardwareNexus6P(HardwareAndroid):
echo 9887 > /sys/class/devfreq/qcom,gpubw.70/max_freq
echo 9887 > /sys/class/devfreq/qcom,gpubw.70/min_freq''')
- def _unlock_clocks(self):
- if not self._adb.is_root():
- return
-
- # restore ddr settings to default.
- self._adb.shell('''\
- echo 1525 > /sys/class/devfreq/qcom,cpubw.32/min_freq
- echo 9887 > /sys/class/devfreq/qcom,cpubw.32/max_freq
- echo bw_hwmon > /sys/class/devfreq/qcom,cpubw.32/governor
- echo 1525 > /sys/class/devfreq/qcom,gpubw.70/min_freq
- echo 9887 > /sys/class/devfreq/qcom,gpubw.70/max_freq
- echo bw_hwmon > /sys/class/devfreq/qcom,gpubw.70/governor''')
-
- # restore gpu settings to default.
- self._adb.shell('''\
- echo 180000000 > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
- echo 600000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
- echo 180000000 > /sys/class/kgsl/kgsl-3d0/gpuclk
- echo msm-adreno-tz > /sys/class/kgsl/kgsl-3d0/devfreq/governor
- echo 0 > /sys/class/kgsl/kgsl-3d0/idle_timer
- echo 0 > /sys/class/kgsl/kgsl-3d0/force_clk_on
- echo 0 > /sys/class/kgsl/kgsl-3d0/force_rail_on
- echo 0 > /sys/class/kgsl/kgsl-3d0/force_bus_on
- echo 1 > /sys/class/kgsl/kgsl-3d0/bus_split''')
-
- # turn the disabled cores back on.
- self._adb.shell('''\
- for N in 7 3 2 1 0; do
- echo 1 > /sys/devices/system/cpu/cpu$N/online
- done''')
-
- # unlock the 3 enabled big cores.
- self._adb.shell('''\
- for N in 6 5 4; do
- echo 633600 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
- echo 1958400 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
- echo 0 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
- echo interactive > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
- done''')
-
- self._adb.shell('''\
- start mpdecision
- start perfd
- start thermald
- start thermal-engine''')
+ return self
def sanity_check(self):
HardwareAndroid.sanity_check(self)
@@ -148,8 +96,3 @@ class HardwareNexus6P(HardwareAndroid):
for i in range(4, 7)]
Expectation.check_all(expectations, result.splitlines())
-
- def sleep(self, sleeptime):
- self._unlock_clocks()
- HardwareAndroid.sleep(self, sleeptime)
- self._lock_clocks()
diff --git a/chromium/third_party/skia/tools/skpbench/_hardware_pixel.py b/chromium/third_party/skia/tools/skpbench/_hardware_pixel.py
new file mode 100644
index 00000000000..4cdf21ac8c7
--- /dev/null
+++ b/chromium/third_party/skia/tools/skpbench/_hardware_pixel.py
@@ -0,0 +1,161 @@
+# Copyright 2017 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from _hardware import HardwareException, Expectation
+from _hardware_android import HardwareAndroid
+from collections import namedtuple
+import itertools
+
+CPU_CLOCK_RATE = 1670400
+GPU_CLOCK_RATE = 510000000
+
+DEVFREQ_DIRNAME = '/sys/class/devfreq'
+DEVFREQ_THROTTLE = 0.74
+DEVFREQ_BLACKLIST = ('b00000.qcom,kgsl-3d0', 'soc:qcom,kgsl-busmon',
+ 'soc:qcom,m4m')
+DevfreqKnobs = namedtuple('knobs',
+ ('available_governors', 'available_frequencies',
+ 'governor', 'min_freq', 'max_freq', 'cur_freq'))
+
+class HardwarePixel(HardwareAndroid):
+ def __init__(self, adb):
+ HardwareAndroid.__init__(self, adb)
+ self._discover_devfreqs()
+
+ def __enter__(self):
+ HardwareAndroid.__enter__(self)
+ if not self._adb.is_root():
+ return self
+
+ self._adb.shell('\n'.join(['''\
+ stop thermal-engine
+ stop thermald
+ stop perfd
+ stop mpdecision''',
+
+ # enable and lock the two fast cores.
+ '''
+ for N in 3 2; do
+ echo 1 > /sys/devices/system/cpu/cpu$N/online
+ echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
+ echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
+ done''' % tuple(CPU_CLOCK_RATE for _ in range(3)),
+
+ # turn off the two slow cores
+ '''
+ for N in 1 0; do
+ echo 0 > /sys/devices/system/cpu/cpu$N/online
+ done''',
+
+ # gpu perf commands from
+ # https://developer.qualcomm.com/qfile/28823/lm80-p0436-11_adb_commands.pdf
+ '''
+ echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split
+ echo 1 > /sys/class/kgsl/kgsl-3d0/force_bus_on
+ echo 1 > /sys/class/kgsl/kgsl-3d0/force_rail_on
+ echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on
+ echo 1000000 > /sys/class/kgsl/kgsl-3d0/idle_timer
+ echo userspace > /sys/class/kgsl/kgsl-3d0/devfreq/governor
+ echo 2 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
+ echo 2 > /sys/class/kgsl/kgsl-3d0/min_pwrlevel
+ echo 2 > /sys/class/kgsl/kgsl-3d0/thermal_pwrlevel
+ echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
+ echo %i > /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
+ echo %i > /sys/class/kgsl/kgsl-3d0/max_gpuclk
+ echo %i > /sys/class/kgsl/kgsl-3d0/gpuclk''' %
+ tuple(GPU_CLOCK_RATE for _ in range(4))] + \
+
+ self._devfreq_lock_cmds))
+
+ return self
+
+ def sanity_check(self):
+ HardwareAndroid.sanity_check(self)
+
+ if not self._adb.is_root():
+ return
+
+ result = self._adb.check(' '.join(
+ ['cat',
+ '/sys/class/power_supply/battery/capacity',
+ '/sys/devices/system/cpu/online'] + \
+ ['/sys/devices/system/cpu/cpu%i/cpufreq/scaling_cur_freq' % i
+ for i in range(2, 4)] + \
+ ['/sys/class/kgsl/kgsl-3d0/thermal_pwrlevel',
+ '/sys/kernel/debug/clk/gpu_gx_gfx3d_clk/measure',
+ '/sys/kernel/debug/clk/bimc_clk/measure',
+ '/sys/class/thermal/thermal_zone22/temp',
+ '/sys/class/thermal/thermal_zone23/temp'] + \
+ self._devfreq_sanity_knobs))
+
+ expectations = \
+ [Expectation(int, min_value=30, name='battery', sleeptime=30*60),
+ Expectation(str, exact_value='2-3', name='online cpus')] + \
+ [Expectation(int, exact_value=CPU_CLOCK_RATE, name='cpu_%i clock rate' %i)
+ for i in range(2, 4)] + \
+ [Expectation(int, exact_value=2, name='gpu thermal power level'),
+ Expectation(long, min_value=(GPU_CLOCK_RATE - 5000),
+ max_value=(GPU_CLOCK_RATE + 5000),
+ name='measured gpu clock'),
+ Expectation(long, min_value=902390000, max_value=902409999,
+ name='measured ddr clock', sleeptime=10),
+ Expectation(int, max_value=41000, name='pm8994_tz temperature'),
+ Expectation(int, max_value=40, name='msm_therm temperature')] + \
+ self._devfreq_sanity_expectations
+
+ Expectation.check_all(expectations, result.splitlines())
+
+ def _discover_devfreqs(self):
+ self._devfreq_lock_cmds = list()
+ self._devfreq_sanity_knobs = list()
+ self._devfreq_sanity_expectations = list()
+
+ results = iter(self._adb.check('''\
+ KNOBS='%s'
+ for DEVICE in %s/*; do
+ if cd $DEVICE && ls $KNOBS >/dev/null; then
+ basename $DEVICE
+ cat $KNOBS
+ fi
+ done 2>/dev/null''' %
+ (' '.join(DevfreqKnobs._fields), DEVFREQ_DIRNAME)).splitlines())
+
+ while True:
+ batch = tuple(itertools.islice(results, 1 + len(DevfreqKnobs._fields)))
+ if not batch:
+ break
+
+ devfreq = batch[0]
+ if devfreq in DEVFREQ_BLACKLIST:
+ continue
+
+ path = '%s/%s' % (DEVFREQ_DIRNAME, devfreq)
+
+ knobs = DevfreqKnobs(*batch[1:])
+ if not 'performance' in knobs.available_governors.split():
+ print('WARNING: devfreq %s does not have performance governor' % path)
+ continue
+
+ self._devfreq_lock_cmds.append('echo performance > %s/governor' % path)
+
+ frequencies = map(int, knobs.available_frequencies.split())
+ if frequencies:
+ # choose the lowest frequency that is >= DEVFREQ_THROTTLE * max.
+ frequencies.sort()
+ target = DEVFREQ_THROTTLE * frequencies[-1]
+ idx = len(frequencies) - 1
+ while idx > 0 and frequencies[idx - 1] >= target:
+ idx -= 1
+ bench_frequency = frequencies[idx]
+ self._devfreq_lock_cmds.append('echo %i > %s/min_freq' %
+ (bench_frequency, path))
+ self._devfreq_lock_cmds.append('echo %i > %s/max_freq' %
+ (bench_frequency, path))
+ self._devfreq_sanity_knobs.append('%s/cur_freq' % path)
+ self._devfreq_sanity_expectations.append(
+ Expectation(int, exact_value=bench_frequency,
+ name='%s/cur_freq' % path))
diff --git a/chromium/third_party/skia/tools/skpbench/_hardware_pixel_c.py b/chromium/third_party/skia/tools/skpbench/_hardware_pixel_c.py
index a1cd17a0846..037ae215c22 100644
--- a/chromium/third_party/skia/tools/skpbench/_hardware_pixel_c.py
+++ b/chromium/third_party/skia/tools/skpbench/_hardware_pixel_c.py
@@ -15,22 +15,9 @@ class HardwarePixelC(HardwareAndroid):
HardwareAndroid.__init__(self, adb)
def __enter__(self):
- self._lock_clocks()
- return HardwareAndroid.__enter__(self)
-
- def __exit__(self, exception_type, exception_value, exception_traceback):
- HardwareAndroid.__exit__(self, exception_type,
- exception_value, exception_traceback)
- self._unlock_clocks()
-
- def filter_line(self, line):
- JUNK = ['NvRmPrivGetChipPlatform: Could not read platform information',
- 'Expected on kernels without fuse support, using silicon']
- return False if line in JUNK else HardwareAndroid.filter_line(self, line)
-
- def _lock_clocks(self):
+ HardwareAndroid.__enter__(self)
if not self._adb.is_root():
- return
+ return self
self._adb.shell('\n'.join([
# turn on and lock the first 3 cores.
@@ -52,28 +39,12 @@ class HardwarePixelC(HardwareAndroid):
chown root:root /sys/devices/57000000.gpu/pstate
echo %s > /sys/devices/57000000.gpu/pstate''' % GPU_EMC_PROFILE_ID]))
- def _unlock_clocks(self):
- if not self._adb.is_root():
- return
+ return self
- self._adb.shell('\n'.join([
- # unlock gpu/emc clocks.
- '''
- echo auto > /sys/devices/57000000.gpu/pstate
- chown system:system /sys/devices/57000000.gpu/pstate''',
-
- # turn the fourth core back on.
- '''
- echo 1 > /sys/devices/system/cpu/cpu3/online''',
-
- # unlock the first 3 cores.
- '''
- for N in 2 1 0; do
- echo 1912500 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_max_freq
- echo 51000 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_min_freq
- echo 0 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
- echo interactive >/sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
- done''']))
+ def filter_line(self, line):
+ JUNK = ['NvRmPrivGetChipPlatform: Could not read platform information',
+ 'Expected on kernels without fuse support, using silicon']
+ return False if line in JUNK else HardwareAndroid.filter_line(self, line)
def sanity_check(self):
HardwareAndroid.sanity_check(self)
@@ -109,8 +80,3 @@ class HardwarePixelC(HardwareAndroid):
[Expectation(str, exact_value=GPU_EMC_PROFILE, name='gpu/emc profile')]
Expectation.check_all(expectations, result.splitlines())
-
- def sleep(self, sleeptime):
- self._unlock_clocks()
- HardwareAndroid.sleep(self, sleeptime)
- self._lock_clocks()
diff --git a/chromium/third_party/skia/tools/skpbench/skpbench.cpp b/chromium/third_party/skia/tools/skpbench/skpbench.cpp
index c0ead46155e..ef7a5bbabf6 100644
--- a/chromium/third_party/skia/tools/skpbench/skpbench.cpp
+++ b/chromium/third_party/skia/tools/skpbench/skpbench.cpp
@@ -10,6 +10,7 @@
#include "SkGr.h"
#include "SkCanvas.h"
+#include "SkCommonFlags.h"
#include "SkCommonFlagsPathRenderer.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
@@ -277,6 +278,7 @@ int main(int argc, char** argv) {
// Create a context.
GrContextOptions ctxOptions;
ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+ ctxOptions.fAllowPathMaskCaching = FLAGS_cachePathMasks;
sk_gpu_test::GrContextFactory factory(ctxOptions);
sk_gpu_test::ContextInfo ctxInfo =
factory.getContextInfo(config->getContextType(), config->getContextOverrides());
diff --git a/chromium/third_party/skia/tools/skpbench/skpbench.py b/chromium/third_party/skia/tools/skpbench/skpbench.py
index ef44577c532..f2df9b679d8 100755
--- a/chromium/third_party/skia/tools/skpbench/skpbench.py
+++ b/chromium/third_party/skia/tools/skpbench/skpbench.py
@@ -33,6 +33,8 @@ __argparse.add_argument('skpbench',
help="path to the skpbench binary")
__argparse.add_argument('--adb',
action='store_true', help="execute skpbench over adb")
+__argparse.add_argument('--adb_binary', default='adb',
+ help="The name of the adb binary to use.")
__argparse.add_argument('-s', '--device-serial',
help="if using adb, ID of the specific device to target "
"(only required if more than 1 device is attached)")
@@ -54,6 +56,12 @@ __argparse.add_argument('--gpu',
help="perform timing on the gpu clock instead of cpu (gpu work only)")
__argparse.add_argument('--fps',
action='store_true', help="use fps instead of ms")
+__argparse.add_argument('--pr',
+ help="comma- or space-separated list of GPU path renderers, including: "
+ "[[~]all [~]default [~]dashline [~]nvpr [~]msaa [~]aaconvex "
+ "[~]aalinearizing [~]small [~]tess]")
+__argparse.add_argument('--nocache',
+ action='store_true', help="disable caching of path mask textures")
__argparse.add_argument('-c', '--config',
default='gl', help="comma- or space-separated list of GPU configs")
__argparse.add_argument('-a', '--resultsfile',
@@ -65,7 +73,7 @@ __argparse.add_argument('skps',
FLAGS = __argparse.parse_args()
if FLAGS.adb:
import _adb_path as _path
- _path.init(FLAGS.device_serial)
+ _path.init(FLAGS.device_serial, FLAGS.adb_binary)
else:
import _os_path as _path
@@ -108,11 +116,15 @@ class SKPBench:
ARGV.extend(['--gpuClock', 'true'])
if FLAGS.fps:
ARGV.extend(['--fps', 'true'])
+ if FLAGS.pr:
+ ARGV.extend(['--pr'] + re.split(r'[ ,]', FLAGS.pr))
+ if FLAGS.nocache:
+ ARGV.extend(['--cachePathMasks', 'false'])
if FLAGS.adb:
if FLAGS.device_serial is None:
- ARGV[:0] = ['adb', 'shell']
+ ARGV[:0] = [FLAGS.adb_binary, 'shell']
else:
- ARGV[:0] = ['adb', '-s', FLAGS.device_serial, 'shell']
+ ARGV[:0] = [FLAGS.adb_binary, '-s', FLAGS.device_serial, 'shell']
@classmethod
def get_header(cls, outfile=sys.stdout):
@@ -231,45 +243,53 @@ def emit_result(line, resultsfile=None):
resultsfile.flush()
def run_benchmarks(configs, skps, hardware, resultsfile=None):
- emit_result(SKPBench.get_header(), resultsfile)
+ hasheader = False
benches = collections.deque([(skp, config, FLAGS.max_stddev)
for skp in skps
for config in configs])
while benches:
- benchargs = benches.popleft()
- with SKPBench(*benchargs) as skpbench:
- try:
- skpbench.execute(hardware)
- if skpbench.best_result:
- emit_result(skpbench.best_result.format(FLAGS.suffix), resultsfile)
- else:
- print("WARNING: no result for %s with config %s" %
- (skpbench.skp, skpbench.config), file=sys.stderr)
-
- except StddevException:
- retry_max_stddev = skpbench.max_stddev * math.sqrt(2)
- if FLAGS.verbosity >= 1:
- print("stddev is too high for %s/%s (%s%%, max=%.2f%%), "
- "re-queuing with max=%.2f%%." %
- (skpbench.best_result.config, skpbench.best_result.bench,
- skpbench.best_result.stddev, skpbench.max_stddev,
- retry_max_stddev),
- file=sys.stderr)
- benches.append((skpbench.skp, skpbench.config, retry_max_stddev,
- skpbench.best_result))
-
- except HardwareException as exception:
- skpbench.terminate()
- if FLAGS.verbosity >= 4:
- hardware.print_debug_diagnostics()
- if FLAGS.verbosity >= 1:
- print("%s; taking a %i second nap..." %
- (exception.message, exception.sleeptime), file=sys.stderr)
- benches.appendleft(benchargs) # retry the same bench next time.
- hardware.sleep(exception.sleeptime)
- if FLAGS.verbosity >= 4:
- hardware.print_debug_diagnostics()
+ try:
+ with hardware:
SKPBench.run_warmup(hardware.warmup_time, configs[0])
+ if not hasheader:
+ emit_result(SKPBench.get_header(), resultsfile)
+ hasheader = True
+ while benches:
+ benchargs = benches.popleft()
+ with SKPBench(*benchargs) as skpbench:
+ try:
+ skpbench.execute(hardware)
+ if skpbench.best_result:
+ emit_result(skpbench.best_result.format(FLAGS.suffix),
+ resultsfile)
+ else:
+ print("WARNING: no result for %s with config %s" %
+ (skpbench.skp, skpbench.config), file=sys.stderr)
+
+ except StddevException:
+ retry_max_stddev = skpbench.max_stddev * math.sqrt(2)
+ if FLAGS.verbosity >= 1:
+ print("stddev is too high for %s/%s (%s%%, max=%.2f%%), "
+ "re-queuing with max=%.2f%%." %
+ (skpbench.best_result.config, skpbench.best_result.bench,
+ skpbench.best_result.stddev, skpbench.max_stddev,
+ retry_max_stddev),
+ file=sys.stderr)
+ benches.append((skpbench.skp, skpbench.config, retry_max_stddev,
+ skpbench.best_result))
+
+ except HardwareException as exception:
+ skpbench.terminate()
+ if FLAGS.verbosity >= 4:
+ hardware.print_debug_diagnostics()
+ if FLAGS.verbosity >= 1:
+ print("%s; rebooting and taking a %i second nap..." %
+ (exception.message, exception.sleeptime), file=sys.stderr)
+ benches.appendleft(benchargs) # retry the same bench next time.
+ raise # wake hw up from benchmarking mode before the nap.
+
+ except HardwareException as exception:
+ time.sleep(exception.sleeptime)
def main():
# Delimiter is ',' or ' ', skip if nested inside parens (e.g. gpu(a=b,c=d)).
@@ -278,11 +298,15 @@ def main():
skps = _path.find_skps(FLAGS.skps)
if FLAGS.adb:
- adb = Adb(FLAGS.device_serial, echo=(FLAGS.verbosity >= 5))
+ adb = Adb(FLAGS.device_serial, FLAGS.adb_binary,
+ echo=(FLAGS.verbosity >= 5))
model = adb.check('getprop ro.product.model').strip()
if model == 'Pixel C':
from _hardware_pixel_c import HardwarePixelC
hardware = HardwarePixelC(adb)
+ elif model == 'Pixel':
+ from _hardware_pixel import HardwarePixel
+ hardware = HardwarePixel(adb)
elif model == 'Nexus 6P':
from _hardware_nexus_6p import HardwareNexus6P
hardware = HardwareNexus6P(adb)
@@ -294,13 +318,11 @@ def main():
else:
hardware = Hardware()
- with hardware:
- SKPBench.run_warmup(hardware.warmup_time, configs[0])
- if FLAGS.resultsfile:
- with open(FLAGS.resultsfile, mode='a+') as resultsfile:
- run_benchmarks(configs, skps, hardware, resultsfile=resultsfile)
- else:
- run_benchmarks(configs, skps, hardware)
+ if FLAGS.resultsfile:
+ with open(FLAGS.resultsfile, mode='a+') as resultsfile:
+ run_benchmarks(configs, skps, hardware, resultsfile=resultsfile)
+ else:
+ run_benchmarks(configs, skps, hardware)
if __name__ == '__main__':
diff --git a/chromium/third_party/skia/tools/valgrind.supp b/chromium/third_party/skia/tools/valgrind.supp
index 064f8efa34b..0108b37ef6f 100644
--- a/chromium/third_party/skia/tools/valgrind.supp
+++ b/chromium/third_party/skia/tools/valgrind.supp
@@ -6,7 +6,7 @@
Memcheck:Leak
match-leak-kinds: possible,definite
...
- fun:_ZN8SkThreadC1EPFvPvES0_
+ fun:start_keepalive
...
fun:main
...
diff --git a/chromium/third_party/skia/tools/viewer/SampleSlide.cpp b/chromium/third_party/skia/tools/viewer/SampleSlide.cpp
index 93a495eb8c7..7c6fe11feaf 100644
--- a/chromium/third_party/skia/tools/viewer/SampleSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/SampleSlide.cpp
@@ -9,16 +9,21 @@
#include "SkCanvas.h"
#include "SkCommonFlags.h"
+#include "SkKey.h"
#include "SkOSFile.h"
#include "SkStream.h"
-SampleSlide::SampleSlide(const SkViewFactory* factory) : fViewFactory(factory) {
+using namespace sk_app;
+
+SampleSlide::SampleSlide(const SkViewFactory* factory)
+ : fViewFactory(factory)
+ , fClick(nullptr) {
SkView* view = (*factory)();
SampleCode::RequestTitle(view, &fName);
view->unref();
}
-SampleSlide::~SampleSlide() {}
+SampleSlide::~SampleSlide() { delete fClick; }
void SampleSlide::draw(SkCanvas* canvas) {
SkASSERT(fView);
@@ -45,10 +50,43 @@ bool SampleSlide::onChar(SkUnichar c) {
return fView->doQuery(&evt);
}
-#if defined(SK_BUILD_FOR_ANDROID)
-// these are normally defined in SkOSWindow_unix, but we don't
-// want to include that
-void SkEvent::SignalNonEmptyQueue() {}
+bool SampleSlide::onMouse(SkScalar x, SkScalar y, Window::InputState state,
+ uint32_t modifiers) {
+ // map to SkView modifiers
+ unsigned modifierKeys = 0;
+ modifierKeys |= (state & Window::kShift_ModifierKey) ? kShift_SkModifierKey : 0;
+ modifierKeys |= (state & Window::kControl_ModifierKey) ? kControl_SkModifierKey : 0;
+ modifierKeys |= (state & Window::kOption_ModifierKey) ? kOption_SkModifierKey : 0;
+ modifierKeys |= (state & Window::kCommand_ModifierKey) ? kCommand_SkModifierKey : 0;
+
+ bool handled = false;
+ switch (state) {
+ case Window::kDown_InputState: {
+ delete fClick;
+ fClick = fView->findClickHandler(SkIntToScalar(x), SkIntToScalar(y), modifierKeys);
+ if (fClick) {
+ SkView::DoClickDown(fClick, x, y, modifierKeys);
+ handled = true;
+ }
+ break;
+ }
+ case Window::kMove_InputState: {
+ if (fClick) {
+ SkView::DoClickMoved(fClick, x, y, modifierKeys);
+ handled = true;
+ }
+ break;
+ }
+ case Window::kUp_InputState: {
+ if (fClick) {
+ SkView::DoClickUp(fClick, x, y, modifierKeys);
+ delete fClick;
+ fClick = nullptr;
+ handled = true;
+ }
+ break;
+ }
+ }
-void SkEvent::SignalQueueTimer(SkMSec delay) {}
-#endif
+ return handled;
+}
diff --git a/chromium/third_party/skia/tools/viewer/SampleSlide.h b/chromium/third_party/skia/tools/viewer/SampleSlide.h
index 24325c91a02..4b91f39f746 100644
--- a/chromium/third_party/skia/tools/viewer/SampleSlide.h
+++ b/chromium/third_party/skia/tools/viewer/SampleSlide.h
@@ -27,10 +27,13 @@ public:
}
bool onChar(SkUnichar c) override;
+ bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
+ uint32_t modifiers) override;
private:
const SkViewFactory* fViewFactory;
sk_sp<SkView> fView;
+ SkView::Click* fClick;
};
#endif
diff --git a/chromium/third_party/skia/tools/viewer/Slide.h b/chromium/third_party/skia/tools/viewer/Slide.h
index 9ec7a3dbe19..e23a2eb78d3 100644
--- a/chromium/third_party/skia/tools/viewer/Slide.h
+++ b/chromium/third_party/skia/tools/viewer/Slide.h
@@ -11,6 +11,7 @@
#include "SkRefCnt.h"
#include "SkSize.h"
#include "SkString.h"
+#include "sk_app/Window.h"
class SkCanvas;
class SkAnimTimer;
@@ -29,9 +30,12 @@ public:
virtual void unload() {}
virtual bool onChar(SkUnichar c) { return false; }
+ virtual bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
+ uint32_t modifiers) { return false; }
SkString getName() { return fName; }
+
protected:
SkString fName;
};
diff --git a/chromium/third_party/skia/tools/viewer/Viewer.cpp b/chromium/third_party/skia/tools/viewer/Viewer.cpp
index e1f72d7575e..8c320938fb0 100644
--- a/chromium/third_party/skia/tools/viewer/Viewer.cpp
+++ b/chromium/third_party/skia/tools/viewer/Viewer.cpp
@@ -17,6 +17,7 @@
#include "SkATrace.h"
#include "SkCanvas.h"
#include "SkColorSpace_Base.h"
+#include "SkColorSpacePriv.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkCommonFlagsGpuThreads.h"
@@ -35,6 +36,7 @@
#include "SkSurface.h"
#include "SkSwizzle.h"
#include "SkTaskGroup.h"
+#include "SkThreadedBMPDevice.h"
#include "SkTime.h"
#include "SkVertices.h"
@@ -140,8 +142,8 @@ static DEFINE_string2(match, m, nullptr,
"If a bench does not match any list entry,\n"
"it is skipped unless some list entry starts with ~");
-DEFINE_string(slide, "", "Start on this sample.");
-DEFINE_bool(list, false, "List samples?");
+static DEFINE_string(slide, "", "Start on this sample.");
+static DEFINE_bool(list, false, "List samples?");
#ifdef SK_VULKAN
# define BACKENDS_STR "\"sw\", \"gl\", and \"vk\""
@@ -159,10 +161,11 @@ static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");
-DEFINE_int32(msaa, 0, "Number of subpixel samples. 0 for no HW antialiasing.");
+static DEFINE_int32(msaa, 0, "Number of subpixel samples. 0 for no HW antialiasing.");
+static DEFINE_bool(cachePathMasks, true, "Allows path mask textures to be cached in GPU configs.");
DEFINE_pathrenderer_flag;
-DEFINE_bool(instancedRendering, false, "Enable instanced rendering on GPU backends.");
+static DEFINE_bool(instancedRendering, false, "Enable instanced rendering on GPU backends.");
DECLARE_int32(threads)
const char* kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
@@ -235,6 +238,12 @@ static bool primaries_equal(const SkColorSpacePrimaries& a, const SkColorSpacePr
return memcmp(&a, &b, sizeof(SkColorSpacePrimaries)) == 0;
}
+static Window::BackendType backend_type_for_window(Window::BackendType backendType) {
+ // In raster mode, we still use GL for the window.
+ // This lets us render the GUI faster (and correct).
+ return Window::kRaster_BackendType == backendType ? Window::kNativeGL_BackendType : backendType;
+}
+
const char* kName = "name";
const char* kValue = "value";
const char* kOptions = "options";
@@ -252,17 +261,24 @@ const char* kRefreshStateName = "Refresh";
Viewer::Viewer(int argc, char** argv, void* platformData)
: fCurrentMeasurement(0)
+ , fCumulativeMeasurementTime(0)
+ , fCumulativeMeasurementCount(0)
, fDisplayStats(false)
, fRefresh(false)
, fShowImGuiDebugWindow(false)
+ , fShowSlidePicker(false)
, fShowImGuiTestWindow(false)
, fShowZoomWindow(false)
, fLastImage(nullptr)
, fBackendType(sk_app::Window::kNativeGL_BackendType)
, fColorMode(ColorMode::kLegacy)
, fColorSpacePrimaries(gSrgbPrimaries)
+ // Our UI can only tweak gamma (currently), so start out gamma-only
+ , fColorSpaceTransferFn(g2Dot2_TransferFn)
, fZoomLevel(0.0f)
, fGestureDevice(GestureDevice::kNone)
+ , fTileCnt(0)
+ , fThreadCnt(0)
{
SkGraphics::Init();
@@ -304,6 +320,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
displayParams.fMSAASampleCount = FLAGS_msaa;
displayParams.fGrContextOptions.fEnableInstancedRendering = FLAGS_instancedRendering;
displayParams.fGrContextOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+ displayParams.fGrContextOptions.fAllowPathMaskCaching = FLAGS_cachePathMasks;
displayParams.fGrContextOptions.fExecutor = GpuExecutorForTools();
fWindow->setRequestedDisplayParams(displayParams);
@@ -323,6 +340,18 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
fWindow->inval();
});
+ // Command to jump directly to the slide picker and give it focus
+ fCommands.addCommand('/', "GUI", "Jump to slide picker", [this]() {
+ this->fShowImGuiDebugWindow = true;
+ this->fShowSlidePicker = true;
+ fWindow->inval();
+ });
+ // Alias that to Backspace, to match SampleApp
+ fCommands.addCommand(Window::Key::kBack, "Backspace", "GUI", "Jump to slide picker", [this]() {
+ this->fShowImGuiDebugWindow = true;
+ this->fShowSlidePicker = true;
+ fWindow->inval();
+ });
fCommands.addCommand('g', "GUI", "Toggle GUI Demo", [this]() {
this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
fWindow->inval();
@@ -335,6 +364,11 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
this->fDisplayStats = !this->fDisplayStats;
fWindow->inval();
});
+ fCommands.addCommand('0', "Overlays", "Reset stats", [this]() {
+ this->resetMeasurements();
+ this->updateTitle();
+ fWindow->inval();
+ });
fCommands.addCommand('c', "Modes", "Cycle color mode", [this]() {
switch (fColorMode) {
case ColorMode::kLegacy:
@@ -390,7 +424,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
this->setBackend(newBackend);
});
- fCommands.addCommand('A', "AAA", "Toggle analytic AA", [this]() {
+ fCommands.addCommand('A', "AA", "Toggle analytic AA", [this]() {
if (!gSkUseAnalyticAA) {
gSkUseAnalyticAA = true;
} else if (!gSkForceAnalyticAA) {
@@ -401,7 +435,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
this->updateTitle();
fWindow->inval();
});
- fCommands.addCommand('D', "DAA", "Toggle delta AA", [this]() {
+ fCommands.addCommand('D', "AA", "Toggle delta AA", [this]() {
if (!gSkUseDeltaAA) {
gSkUseDeltaAA = true;
} else if (!gSkForceDeltaAA) {
@@ -413,6 +447,41 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fWindow->inval();
});
+ fCommands.addCommand('+', "Threaded Backend", "Increase tile count", [this]() {
+ fTileCnt++;
+ if (fThreadCnt == 0) {
+ this->resetExecutor();
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('-', "Threaded Backend", "Decrease tile count", [this]() {
+ fTileCnt = SkTMax(0, fTileCnt - 1);
+ if (fThreadCnt == 0) {
+ this->resetExecutor();
+ }
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('>', "Threaded Backend", "Increase thread count", [this]() {
+ if (fTileCnt == 0) {
+ return;
+ }
+ fThreadCnt = (fThreadCnt + 1) % fTileCnt;
+ this->resetExecutor();
+ this->updateTitle();
+ fWindow->inval();
+ });
+ fCommands.addCommand('<', "Threaded Backend", "Decrease thread count", [this]() {
+ if (fTileCnt == 0) {
+ return;
+ }
+ fThreadCnt = (fThreadCnt + fTileCnt - 1) % fTileCnt;
+ this->resetExecutor();
+ this->updateTitle();
+ fWindow->inval();
+ });
+
// set up slides
this->initSlides();
this->setStartupSlide();
@@ -468,7 +537,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fImGuiGamutPaint.setColor(SK_ColorWHITE);
fImGuiGamutPaint.setFilterQuality(kLow_SkFilterQuality);
- fWindow->attach(fBackendType);
+ fWindow->attach(backend_type_for_window(fBackendType));
}
void Viewer::initSlides() {
@@ -581,6 +650,13 @@ void Viewer::updateTitle() {
}
}
+ if (fTileCnt > 0) {
+ title.appendf(" T%d", fTileCnt);
+ if (fThreadCnt > 0) {
+ title.appendf("/%d", fThreadCnt);
+ }
+ }
+
switch (fColorMode) {
case ColorMode::kLegacy:
title.append(" Legacy 8888");
@@ -605,6 +681,10 @@ void Viewer::updateTitle() {
}
}
title.appendf(" %s", curPrimaries >= 0 ? gNamedPrimaries[curPrimaries].fName : "Custom");
+
+ if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
+ title.appendf(" Gamma %f", fColorSpaceTransferFn.fG);
+ }
}
title.append(" [");
@@ -648,6 +728,15 @@ void Viewer::listNames() {
}
}
+void Viewer::resetMeasurements() {
+ memset(fPaintTimes, 0, sizeof(fPaintTimes));
+ memset(fFlushTimes, 0, sizeof(fFlushTimes));
+ memset(fAnimateTimes, 0, sizeof(fAnimateTimes));
+ fCurrentMeasurement = 0;
+ fCumulativeMeasurementTime = 0;
+ fCumulativeMeasurementCount = 0;
+}
+
void Viewer::setupCurrentSlide(int previousSlide) {
if (fCurrentSlide == previousSlide) {
return; // no change; do nothing
@@ -677,6 +766,9 @@ void Viewer::setupCurrentSlide(int previousSlide) {
if (previousSlide >= 0) {
fSlides[previousSlide]->unload();
}
+
+ this->resetMeasurements();
+
fWindow->inval();
}
@@ -706,40 +798,33 @@ void Viewer::setBackend(sk_app::Window::BackendType backendType) {
fWindow->detach();
-#if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN)
+#if defined(SK_BUILD_FOR_WIN)
// Switching between OpenGL, Vulkan, and ANGLE in the same window is problematic at this point
// on Windows, so we just delete the window and recreate it.
- if (sk_app::Window::kVulkan_BackendType == fBackendType ||
- sk_app::Window::kNativeGL_BackendType == fBackendType
-#if SK_ANGLE
- || sk_app::Window::kANGLE_BackendType == fBackendType
-#endif
- ) {
- DisplayParams params = fWindow->getRequestedDisplayParams();
- delete fWindow;
- fWindow = Window::CreateNativeWindow(nullptr);
-
- // re-register callbacks
- fCommands.attach(fWindow);
- fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
- fWindow->registerPaintFunc(on_paint_handler, this);
- fWindow->registerTouchFunc(on_touch_handler, this);
- fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
- fWindow->registerMouseFunc(on_mouse_handler, this);
- fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
- fWindow->registerKeyFunc(on_key_handler, this);
- fWindow->registerCharFunc(on_char_handler, this);
- // Don't allow the window to re-attach. If we're in MSAA mode, the params we grabbed above
- // will still include our correct sample count. But the re-created fWindow will lose that
- // information. On Windows, we need to re-create the window when changing sample count,
- // so we'll incorrectly detect that situation, then re-initialize the window in GL mode,
- // rendering this tear-down step pointless (and causing the Vulkan window context to fail
- // as if we had never changed windows at all).
- fWindow->setRequestedDisplayParams(params, false);
- }
+ DisplayParams params = fWindow->getRequestedDisplayParams();
+ delete fWindow;
+ fWindow = Window::CreateNativeWindow(nullptr);
+
+ // re-register callbacks
+ fCommands.attach(fWindow);
+ fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
+ fWindow->registerPaintFunc(on_paint_handler, this);
+ fWindow->registerTouchFunc(on_touch_handler, this);
+ fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
+ fWindow->registerMouseFunc(on_mouse_handler, this);
+ fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
+ fWindow->registerKeyFunc(on_key_handler, this);
+ fWindow->registerCharFunc(on_char_handler, this);
+ // Don't allow the window to re-attach. If we're in MSAA mode, the params we grabbed above
+ // will still include our correct sample count. But the re-created fWindow will lose that
+ // information. On Windows, we need to re-create the window when changing sample count,
+ // so we'll incorrectly detect that situation, then re-initialize the window in GL mode,
+ // rendering this tear-down step pointless (and causing the Vulkan window context to fail
+ // as if we had never changed windows at all).
+ fWindow->setRequestedDisplayParams(params, false);
#endif
- fWindow->attach(fBackendType);
+ fWindow->attach(backend_type_for_window(fBackendType));
}
void Viewer::setColorMode(ColorMode colorMode) {
@@ -774,13 +859,21 @@ void Viewer::drawSlide(SkCanvas* canvas) {
? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
SkMatrix44 toXYZ(SkMatrix44::kIdentity_Constructor);
SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
- cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
+ if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
+ cs = SkColorSpace::MakeRGB(fColorSpaceTransferFn, toXYZ);
+ } else {
+ cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
+ }
}
// If we're in F16, or we're zooming, or we're in color correct 8888 and the gamut isn't sRGB,
- // we need to render offscreen
+ // we need to render offscreen. We also need to render offscreen if we're in any raster mode,
+ // because the window surface is actually GL.
sk_sp<SkSurface> offscreenSurface = nullptr;
- if (ColorMode::kColorManagedLinearF16 == fColorMode ||
+ std::unique_ptr<SkThreadedBMPDevice> threadedDevice;
+ std::unique_ptr<SkCanvas> threadedCanvas;
+ if (Window::kRaster_BackendType == fBackendType ||
+ ColorMode::kColorManagedLinearF16 == fColorMode ||
fShowZoomWindow ||
(ColorMode::kColorManagedSRGB8888 == fColorMode &&
!primaries_equal(fColorSpacePrimaries, gSrgbPrimaries))) {
@@ -793,8 +886,19 @@ void Viewer::drawSlide(SkCanvas* canvas) {
(ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) ? nullptr : cs;
SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), colorType,
kPremul_SkAlphaType, std::move(offscreenColorSpace));
- offscreenSurface = canvas->makeSurface(info);
- slideCanvas = offscreenSurface->getCanvas();
+ offscreenSurface = Window::kRaster_BackendType == fBackendType ? SkSurface::MakeRaster(info)
+ : canvas->makeSurface(info);
+ SkPixmap offscreenPixmap;
+ if (fTileCnt > 0 && offscreenSurface->peekPixels(&offscreenPixmap)) {
+ SkBitmap offscreenBitmap;
+ offscreenBitmap.installPixels(offscreenPixmap);
+ threadedDevice.reset(new SkThreadedBMPDevice(offscreenBitmap, fTileCnt,
+ fThreadCnt, fExecutor.get()));
+ threadedCanvas.reset(new SkCanvas(threadedDevice.get()));
+ slideCanvas = threadedCanvas.get();
+ } else {
+ slideCanvas = offscreenSurface->getCanvas();
+ }
}
std::unique_ptr<SkCanvas> xformCanvas = nullptr;
@@ -835,6 +939,7 @@ void Viewer::onBackendCreated() {
this->updateTitle();
this->updateUIState();
this->setupCurrentSlide(-1);
+ this->resetMeasurements();
fWindow->show();
fWindow->inval();
}
@@ -852,9 +957,13 @@ void Viewer::onPaint(SkCanvas* canvas) {
ImGui::NewFrame();
- drawSlide(canvas);
+ this->drawSlide(canvas);
// Advance our timing bookkeeping
+ fCumulativeMeasurementTime += fAnimateTimes[fCurrentMeasurement] +
+ fPaintTimes[fCurrentMeasurement] +
+ fFlushTimes[fCurrentMeasurement];
+ fCumulativeMeasurementCount++;
fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
SkASSERT(fCurrentMeasurement < kMeasurementCount);
@@ -864,10 +973,10 @@ void Viewer::onPaint(SkCanvas* canvas) {
}
fCommands.drawHelp(canvas);
- drawImGui(canvas);
+ this->drawImGui(canvas);
// Update the FPS
- updateUIState();
+ this->updateUIState();
}
bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
@@ -895,32 +1004,36 @@ bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y)
}
bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifiers) {
- if (GestureDevice::kTouch == fGestureDevice) {
- return false;
- }
- switch (state) {
- case Window::kUp_InputState: {
- fGesture.touchEnd(nullptr);
- break;
- }
- case Window::kDown_InputState: {
- fGesture.touchBegin(nullptr, x, y);
- break;
+ if (!fSlides[fCurrentSlide]->onMouse(x, y, state, modifiers)) {
+ if (GestureDevice::kTouch == fGestureDevice) {
+ return false;
}
- case Window::kMove_InputState: {
- fGesture.touchMoved(nullptr, x, y);
- break;
+ switch (state) {
+ case Window::kUp_InputState: {
+ fGesture.touchEnd(nullptr);
+ break;
+ }
+ case Window::kDown_InputState: {
+ fGesture.touchBegin(nullptr, x, y);
+ break;
+ }
+ case Window::kMove_InputState: {
+ fGesture.touchMoved(nullptr, x, y);
+ break;
+ }
}
+ fGestureDevice = fGesture.isBeingTouched() ? GestureDevice::kMouse : GestureDevice::kNone;
}
- fGestureDevice = fGesture.isBeingTouched() ? GestureDevice::kMouse : GestureDevice::kNone;
fWindow->inval();
return true;
}
void Viewer::drawStats(SkCanvas* canvas) {
static const float kPixelPerMS = 2.0f;
- static const int kDisplayWidth = 130;
- static const int kDisplayHeight = 100;
+ static const int kDisplayWidth = 192;
+ static const int kGraphHeight = 100;
+ static const int kTextHeight = 60;
+ static const int kDisplayHeight = kGraphHeight + kTextHeight;
static const int kDisplayPadding = 10;
static const int kGraphPadding = 3;
static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
@@ -932,7 +1045,6 @@ void Viewer::drawStats(SkCanvas* canvas) {
SkPaint paint;
canvas->save();
- canvas->clipRect(rect);
paint.setColor(SK_ColorBLACK);
canvas->drawRect(rect, paint);
// draw the 16ms line
@@ -942,35 +1054,73 @@ void Viewer::drawStats(SkCanvas* canvas) {
paint.setColor(SK_ColorRED);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(rect, paint);
+ paint.setStyle(SkPaint::kFill_Style);
int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
- const int xStep = 2;
+ const int xStep = 3;
int i = fCurrentMeasurement;
+ double ms = 0;
+ double animateMS = 0;
+ double paintMS = 0;
+ double flushMS = 0;
+ int count = 0;
do {
// Round to nearest values
int animateHeight = (int)(fAnimateTimes[i] * kPixelPerMS + 0.5);
int paintHeight = (int)(fPaintTimes[i] * kPixelPerMS + 0.5);
int flushHeight = (int)(fFlushTimes[i] * kPixelPerMS + 0.5);
int startY = SkScalarTruncToInt(rect.fBottom);
- int endY = startY - flushHeight;
+ int endY = SkTMax(startY - flushHeight, kDisplayPadding + kTextHeight);
paint.setColor(SK_ColorRED);
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
SkIntToScalar(x), SkIntToScalar(endY), paint);
startY = endY;
- endY = startY - paintHeight;
+ endY = SkTMax(startY - paintHeight, kDisplayPadding + kTextHeight);
paint.setColor(SK_ColorGREEN);
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
SkIntToScalar(x), SkIntToScalar(endY), paint);
startY = endY;
- endY = startY - animateHeight;
+ endY = SkTMax(startY - animateHeight, kDisplayPadding + kTextHeight);
paint.setColor(SK_ColorMAGENTA);
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
SkIntToScalar(x), SkIntToScalar(endY), paint);
+
+ double inc = fAnimateTimes[i] + fPaintTimes[i] + fFlushTimes[i];
+ if (inc > 0) {
+ ms += inc;
+ animateMS += fAnimateTimes[i];
+ paintMS += fPaintTimes[i];
+ flushMS += fFlushTimes[i];
+ ++count;
+ }
+
i++;
i &= (kMeasurementCount - 1); // fast mod
x += xStep;
} while (i != fCurrentMeasurement);
+ paint.setTextSize(16);
+ SkString mainString;
+ mainString.appendf("%4.3f ms -> %4.3f ms", ms / SkTMax(1, count),
+ fCumulativeMeasurementTime / SkTMax(1, fCumulativeMeasurementCount));
+ paint.setColor(SK_ColorWHITE);
+ canvas->drawString(mainString.c_str(), rect.fLeft+3, rect.fTop + 14, paint);
+
+ SkString animateString;
+ animateString.appendf("Animate: %4.3f ms", animateMS / SkTMax(1, count));
+ paint.setColor(0xffff66ff); // pure magenta is hard to read
+ canvas->drawString(animateString.c_str(), rect.fLeft+3, rect.fTop + 28, paint);
+
+ SkString paintString;
+ paintString.appendf("Paint: %4.3f ms", paintMS / SkTMax(1, count));
+ paint.setColor(SK_ColorGREEN);
+ canvas->drawString(paintString.c_str(), rect.fLeft+3, rect.fTop + 42, paint);
+
+ SkString flushString;
+ flushString.appendf("Flush: %4.3f ms", flushMS / SkTMax(1, count));
+ paint.setColor(0xffff6666); // pure red is hard to read
+ canvas->drawString(flushString.c_str(), rect.fLeft+3, rect.fTop + 56, paint);
+
canvas->restore();
}
@@ -1034,6 +1184,15 @@ static void ImGui_Primaries(SkColorSpacePrimaries* primaries, SkPaint* gamutPain
ImGui::SetCursorPos(endPos);
}
+typedef std::function<void(SkCanvas*)> CustomGuiPainter;
+static SkTArray<CustomGuiPainter> gCustomGuiPainters;
+
+static void ImGui_Skia_Callback(const ImVec2& size, CustomGuiPainter painter) {
+ intptr_t painterIndex = gCustomGuiPainters.count();
+ gCustomGuiPainters.push_back(painter);
+ ImGui::Image((ImTextureID)painterIndex, size);
+}
+
void Viewer::drawImGui(SkCanvas* canvas) {
// Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible
if (fShowImGuiTestWindow) {
@@ -1129,23 +1288,40 @@ void Viewer::drawImGui(SkCanvas* canvas) {
}
}
+ if (fShowSlidePicker) {
+ ImGui::SetNextTreeNodeOpen(true);
+ }
+
if (ImGui::CollapsingHeader("Slide")) {
static ImGuiTextFilter filter;
+ static ImVector<const char*> filteredSlideNames;
+ static ImVector<int> filteredSlideIndices;
+
+ if (fShowSlidePicker) {
+ ImGui::SetKeyboardFocusHere();
+ fShowSlidePicker = false;
+ }
+
filter.Draw();
- int previousSlide = fCurrentSlide;
- fCurrentSlide = 0;
- for (auto slide : fSlides) {
- if (filter.PassFilter(slide->getName().c_str())) {
- ImGui::BulletText("%s", slide->getName().c_str());
- if (ImGui::IsItemClicked()) {
- setupCurrentSlide(previousSlide);
- break;
+ filteredSlideNames.clear();
+ filteredSlideIndices.clear();
+ int filteredIndex = 0;
+ for (int i = 0; i < fSlides.count(); ++i) {
+ const char* slideName = fSlides[i]->getName().c_str();
+ if (filter.PassFilter(slideName) || i == fCurrentSlide) {
+ if (i == fCurrentSlide) {
+ filteredIndex = filteredSlideIndices.size();
}
+ filteredSlideNames.push_back(slideName);
+ filteredSlideIndices.push_back(i);
}
- ++fCurrentSlide;
}
- if (fCurrentSlide >= fSlides.count()) {
- fCurrentSlide = previousSlide;
+
+ int previousSlide = fCurrentSlide;
+ if (ImGui::ListBox("", &filteredIndex, filteredSlideNames.begin(),
+ filteredSlideNames.size(), 20)) {
+ fCurrentSlide = filteredSlideIndices[filteredIndex];
+ setupCurrentSlide(previousSlide);
}
}
@@ -1180,6 +1356,11 @@ void Viewer::drawImGui(SkCanvas* canvas) {
}
}
+ // When we're in xform canvas mode, we can alter the transfer function, too
+ if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
+ ImGui::SliderFloat("Gamma", &fColorSpaceTransferFn.fG, 0.5f, 3.5f);
+ }
+
if (ImGui::Combo("Primaries", &primariesIdx,
"sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
if (primariesIdx >= 0 && primariesIdx <= 3) {
@@ -1201,24 +1382,42 @@ void Viewer::drawImGui(SkCanvas* canvas) {
ImGui::End();
}
- SkPaint zoomImagePaint;
if (fShowZoomWindow && fLastImage) {
if (ImGui::Begin("Zoom", &fShowZoomWindow, ImVec2(200, 200))) {
- static int zoomFactor = 4;
- ImGui::SliderInt("Scale", &zoomFactor, 1, 16);
-
- zoomImagePaint.setShader(fLastImage->makeShader());
- zoomImagePaint.setColor(SK_ColorWHITE);
+ static int zoomFactor = 8;
+ if (ImGui::Button("<<")) {
+ zoomFactor = SkTMax(zoomFactor / 2, 4);
+ }
+ ImGui::SameLine(); ImGui::Text("%2d", zoomFactor); ImGui::SameLine();
+ if (ImGui::Button(">>")) {
+ zoomFactor = SkTMin(zoomFactor * 2, 32);
+ }
- // Zoom by shrinking the corner UVs towards the mouse cursor
ImVec2 mousePos = ImGui::GetMousePos();
ImVec2 avail = ImGui::GetContentRegionAvail();
- ImVec2 zoomHalfExtents = ImVec2((avail.x * 0.5f) / zoomFactor,
- (avail.y * 0.5f) / zoomFactor);
- ImGui::Image(&zoomImagePaint, avail,
- ImVec2(mousePos.x - zoomHalfExtents.x, mousePos.y - zoomHalfExtents.y),
- ImVec2(mousePos.x + zoomHalfExtents.x, mousePos.y + zoomHalfExtents.y));
+ uint32_t pixel = 0;
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
+ if (fLastImage->readPixels(info, &pixel, info.minRowBytes(), mousePos.x, mousePos.y)) {
+ ImGui::SameLine();
+ ImGui::Text("(X, Y): %d, %d RGBA: %x %x %x %x",
+ sk_float_round2int(mousePos.x), sk_float_round2int(mousePos.y),
+ SkGetPackedR32(pixel), SkGetPackedG32(pixel),
+ SkGetPackedB32(pixel), SkGetPackedA32(pixel));
+ }
+
+ ImGui_Skia_Callback(avail, [=](SkCanvas* c) {
+ // Translate so the region of the image that's under the mouse cursor is centered
+ // in the zoom canvas:
+ c->scale(zoomFactor, zoomFactor);
+ c->translate(avail.x * 0.5f / zoomFactor - mousePos.x - 0.5f,
+ avail.y * 0.5f / zoomFactor - mousePos.y - 0.5f);
+ c->drawImage(this->fLastImage, 0, 0);
+
+ SkPaint outline;
+ outline.setStyle(SkPaint::kStroke_Style);
+ c->drawRect(SkRect::MakeXYWH(mousePos.x, mousePos.y, 1, 1), outline);
+ });
}
ImGui::End();
@@ -1254,27 +1453,42 @@ void Viewer::drawImGui(SkCanvas* canvas) {
for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];
+ SkAutoCanvasRestore acr(canvas, true);
+
// TODO: Find min/max index for each draw, so we know how many vertices (sigh)
if (drawCmd->UserCallback) {
drawCmd->UserCallback(drawList, drawCmd);
} else {
- SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
- SkASSERT(paint);
-
- canvas->save();
- canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
- drawCmd->ClipRect.z, drawCmd->ClipRect.w));
- canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
- drawList->VtxBuffer.size(), pos.begin(),
- uv.begin(), color.begin(),
- drawCmd->ElemCount,
- drawList->IdxBuffer.begin() + indexOffset),
- SkBlendMode::kModulate, *paint);
- indexOffset += drawCmd->ElemCount;
- canvas->restore();
+ intptr_t idIndex = (intptr_t)drawCmd->TextureId;
+ if (idIndex < gCustomGuiPainters.count()) {
+ // Small image IDs are actually indices into a list of callbacks. We directly
+ // examing the vertex data to deduce the image rectangle, then reconfigure the
+ // canvas to be clipped and translated so that the callback code gets to use
+ // Skia to render a widget in the middle of an ImGui panel.
+ ImDrawIdx rectIndex = drawList->IdxBuffer[indexOffset];
+ SkPoint tl = pos[rectIndex], br = pos[rectIndex + 2];
+ canvas->clipRect(SkRect::MakeLTRB(tl.fX, tl.fY, br.fX, br.fY));
+ canvas->translate(tl.fX, tl.fY);
+ gCustomGuiPainters[idIndex](canvas);
+ } else {
+ SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
+ SkASSERT(paint);
+
+ canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
+ drawCmd->ClipRect.z, drawCmd->ClipRect.w));
+ auto vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
+ drawList->VtxBuffer.size(),
+ pos.begin(), uv.begin(), color.begin(),
+ drawCmd->ElemCount,
+ drawList->IdxBuffer.begin() + indexOffset);
+ canvas->drawVertices(vertices, SkBlendMode::kModulate, *paint);
+ indexOffset += drawCmd->ElemCount;
+ }
}
}
}
+
+ gCustomGuiPainters.reset();
}
void Viewer::onIdle() {
@@ -1409,7 +1623,7 @@ void Viewer::updateUIState() {
state.append(softkeyState);
state.append(fpsState);
- fWindow->setUIState(state);
+ fWindow->setUIState(state.toStyledString().c_str());
}
void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
@@ -1437,7 +1651,7 @@ void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateVa
if (fBackendType != i) {
fBackendType = (sk_app::Window::BackendType)i;
fWindow->detach();
- fWindow->attach(fBackendType);
+ fWindow->attach(backend_type_for_window(fBackendType));
}
break;
}
diff --git a/chromium/third_party/skia/tools/viewer/Viewer.h b/chromium/third_party/skia/tools/viewer/Viewer.h
index 1b68007ede0..53b75b2de35 100644
--- a/chromium/third_party/skia/tools/viewer/Viewer.h
+++ b/chromium/third_party/skia/tools/viewer/Viewer.h
@@ -13,6 +13,8 @@
#include "sk_app/Window.h"
#include "gm.h"
#include "SkAnimTimer.h"
+#include "SkExecutor.h"
+#include "SkJSONCPP.h"
#include "SkTouchGesture.h"
#include "Slide.h"
@@ -47,6 +49,7 @@ private:
void setStartupSlide();
void setupCurrentSlide(int previousSlide);
void listNames();
+ void resetMeasurements();
void updateUIState();
@@ -57,13 +60,19 @@ private:
void changeZoomLevel(float delta);
SkMatrix computeMatrix();
+ void resetExecutor() {
+ fExecutor = SkExecutor::MakeFIFOThreadPool(fThreadCnt == 0 ? fTileCnt : fThreadCnt);
+ }
+
sk_app::Window* fWindow;
- static const int kMeasurementCount = 64; // should be power of 2 for fast mod
+ static const int kMeasurementCount = 1 << 6; // should be power of 2 for fast mod
double fPaintTimes[kMeasurementCount];
double fFlushTimes[kMeasurementCount];
double fAnimateTimes[kMeasurementCount];
int fCurrentMeasurement;
+ double fCumulativeMeasurementTime;
+ int fCumulativeMeasurementCount;
SkAnimTimer fAnimTimer;
SkTArray<sk_sp<Slide>> fSlides;
@@ -75,6 +84,7 @@ private:
SkPaint fImGuiFontPaint;
SkPaint fImGuiGamutPaint;
bool fShowImGuiDebugWindow;
+ bool fShowSlidePicker;
bool fShowImGuiTestWindow;
bool fShowZoomWindow;
@@ -85,6 +95,7 @@ private:
// Color properties for slide rendering
ColorMode fColorMode;
SkColorSpacePrimaries fColorSpacePrimaries;
+ SkColorSpaceTransferFn fColorSpaceTransferFn;
// transform data
SkScalar fZoomLevel;
@@ -106,6 +117,10 @@ private:
SkTArray<std::function<void(void)>> fDeferredActions;
Json::Value fAllSlideNames; // cache all slide names for fast updateUIState
+
+ int fTileCnt;
+ int fThreadCnt;
+ std::unique_ptr<SkExecutor> fExecutor;
};