aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/skqp/gm_runner.cpp
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2017-12-11 17:46:26 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-15 17:23:48 +0000
commitd7b3845f3d3f3498c2adc542b4b20003ac7d3ab0 (patch)
tree11ed4db86efb28f344255a6cc44f0c19d926c8ef /tools/skqp/gm_runner.cpp
parent0215e39d7e415d0530231df6ad20d5f215c72152 (diff)
SkQP: make_gmkb, gm_knowledge (GM Knowledgebase)
Add a real implementation for gm_knowledge.h This depends on the presence of files in the form $GMK_DIR/foo/{max,min}.png The implementation also writes out failures in a report directory. Add a utility: experimental/make_gmkb which is a stand-alone go executable that generates the foo/{max,min}.png data. tools/skqp/README.md has instructions on running SkQP. Also: add SkFontMgrPriv.h Change-Id: Ibe1e9a7e7de143d14eee3877f5f2d2d8713f7f49 Reviewed-on: https://skia-review.googlesource.com/65380 Reviewed-by: Yuqian Li <liyuqian@google.com> Commit-Queue: Hal Canary <halcanary@google.com>
Diffstat (limited to 'tools/skqp/gm_runner.cpp')
-rw-r--r--tools/skqp/gm_runner.cpp213
1 files changed, 213 insertions, 0 deletions
diff --git a/tools/skqp/gm_runner.cpp b/tools/skqp/gm_runner.cpp
new file mode 100644
index 0000000000..3c3885ef5c
--- /dev/null
+++ b/tools/skqp/gm_runner.cpp
@@ -0,0 +1,213 @@
+/*
+ * 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 "../dm/DMFontMgr.h"
+#include "GrContext.h"
+#include "GrContextOptions.h"
+#include "SkFontMgrPriv.h"
+#include "SkFontStyle.h"
+#include "SkGraphics.h"
+#include "SkSurface.h"
+#include "Test.h"
+#include "gl/GLTestContext.h"
+#include "gm.h"
+#include "gm_knowledge.h"
+#include "vk/VkTestContext.h"
+
+namespace gm_runner {
+
+const char* GetErrorString(Error e) {
+ switch (e) {
+ case Error::None: return "";
+ case Error::BadSkiaOutput: return "Bad Skia Output";
+ case Error::BadGMKBData: return "Bad GMKB Data";
+ case Error::SkiaFailure: return "Skia Failure";
+ default: SkASSERT(false);
+ return "unknown";
+ }
+}
+
+std::vector<std::string> ExecuteTest(UnitTest test) {
+ struct : public skiatest::Reporter {
+ std::vector<std::string> fErrors;
+ void reportFailed(const skiatest::Failure& failure) override {
+ SkString desc = failure.toString();
+ fErrors.push_back(std::string(desc.c_str(), desc.size()));
+ }
+ } r;
+ GrContextOptions options;
+ if (test->fContextOptionsProc) {
+ test->fContextOptionsProc(&options);
+ }
+ test->proc(&r, options);
+ return std::move(r.fErrors);
+}
+
+const char* GetUnitTestName(UnitTest test) { return test->name; }
+
+std::vector<UnitTest> GetUnitTests() {
+ std::vector<UnitTest> tests;
+ for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
+ const skiatest::Test& test = r->factory();
+ if (test.needsGpu) {
+ tests.push_back(&test);
+ }
+ }
+ return tests;
+}
+
+const char* GetBackendName(SkiaBackend backend) {
+ switch (backend) {
+ case SkiaBackend::kGL: return "gl";
+ case SkiaBackend::kGLES: return "gles";
+ case SkiaBackend::kVulkan: return "vk";
+ default: SkASSERT(false);
+ return "error";
+ }
+}
+
+static std::unique_ptr<sk_gpu_test::TestContext> make_test_context(SkiaBackend backend) {
+ using U = std::unique_ptr<sk_gpu_test::TestContext>;
+ switch (backend) {
+ case SkiaBackend::kGL:
+ return U(sk_gpu_test::CreatePlatformGLTestContext(kGL_GrGLStandard, nullptr));
+ case SkiaBackend::kGLES:
+ return U(sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard, nullptr));
+#ifdef SK_VULKAN
+ case SkiaBackend::kVulkan:
+ return U(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
+#endif
+ default:
+ return nullptr;
+ }
+}
+
+static GrContextOptions context_options(skiagm::GM* gm = nullptr) {
+ GrContextOptions grContextOptions;
+ grContextOptions.fAllowPathMaskCaching = true;
+ grContextOptions.fSuppressPathRendering = true;
+ if (gm) {
+ gm->modifyGrContextOptions(&grContextOptions);
+ }
+ return grContextOptions;
+}
+
+std::vector<SkiaBackend> GetSupportedBackends() {
+ std::vector<SkiaBackend> result;
+ SkiaBackend backends[] = {
+ #ifndef SK_BUILD_FOR_ANDROID
+ SkiaBackend::kGL, // Used for testing on desktop machines.
+ #endif
+ SkiaBackend::kGLES,
+ SkiaBackend::kVulkan,
+ };
+ for (SkiaBackend backend : backends) {
+ std::unique_ptr<sk_gpu_test::TestContext> testCtx = make_test_context(backend);
+ if (testCtx) {
+ testCtx->makeCurrent();
+ if (nullptr != testCtx->makeGrContext(context_options())) {
+ result.push_back(backend);
+ }
+ }
+ }
+ return result;
+}
+
+static bool evaluate_gm(SkiaBackend backend,
+ skiagm::GM* gm,
+ int* width,
+ int* height,
+ std::vector<uint32_t>* storage) {
+ constexpr SkColorType ct = kRGBA_8888_SkColorType;
+ SkASSERT(storage);
+ SkASSERT(gm);
+ SkASSERT(width);
+ SkASSERT(height);
+ SkISize size = gm->getISize();
+ int w = size.width(),
+ h = size.height();
+ *width = w;
+ *height = h;
+ SkImageInfo info = SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType, nullptr);
+ SkSurfaceProps props(0, SkSurfaceProps::kLegacyFontHost_InitType);
+
+ std::unique_ptr<sk_gpu_test::TestContext> testCtx = make_test_context(backend);
+ if (!testCtx) {
+ return false;
+ }
+ testCtx->makeCurrent();
+ sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(
+ testCtx->makeGrContext(context_options(gm)).get(), SkBudgeted::kNo, info, 0, &props);
+ if (!surf) {
+ return false;
+ }
+ gm->draw(surf->getCanvas());
+
+ storage->resize(w * h);
+ uint32_t* pix = storage->data();
+ size_t rb = w * sizeof(uint32_t);
+ SkASSERT(SkColorTypeBytesPerPixel(ct) == sizeof(uint32_t));
+ if (!surf->readPixels(SkImageInfo::Make(w, h, ct, kUnpremul_SkAlphaType), pix, rb, 0, 0)) {
+ storage->resize(0);
+ return false;
+ }
+ return true;
+}
+
+std::tuple<float, Error> EvaluateGM(SkiaBackend backend,
+ GMFactory gmFact,
+ skqp::AssetManager* assetManager,
+ const char* reportDirectoryPath) {
+ std::vector<uint32_t> pixels;
+ std::unique_ptr<skiagm::GM> gm(gmFact(nullptr));
+ int width = 0, height = 0;
+ if (!evaluate_gm(backend, gm.get(), &width, &height, &pixels)) {
+ return std::make_tuple(FLT_MAX, Error::SkiaFailure);
+ }
+ gmkb::Error e;
+ float value = gmkb::Check(pixels.data(), width, height,
+ gm->getName(), GetBackendName(backend), assetManager,
+ reportDirectoryPath, &e);
+ Error error = gmkb::Error::kBadInput == e ? Error::BadSkiaOutput
+ : gmkb::Error::kBadData == e ? Error::BadGMKBData
+ : Error::None;
+ return std::make_tuple(value, error);
+}
+
+void InitSkia() {
+ SkGraphics::Init();
+ gSkFontMgr_DefaultFactory = &DM::MakeFontMgr;
+}
+
+std::vector<GMFactory> GetGMFactories(skqp::AssetManager* assetManager) {
+ std::vector<GMFactory> result;
+ for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
+ GMFactory f = r->factory();
+
+ if (gmkb::IsGoodGM(GetGMName(f).c_str(), assetManager)) {
+ result.push_back(r->factory());
+ SkASSERT(result.back());
+ }
+ }
+ 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