1 /*
2 * Copyright 2020 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "gm/gm.h"
9 #include "gm/verifiers/gmverifier.h"
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkSurface.h"
13 #include "include/effects/SkImageFilters.h"
14 #include "include/encode/SkPngEncoder.h"
15 #include "src/utils/SkOSPath.h"
16
17 /** Checks the given VerifierResult. If it is not ok, returns it. */
18 #define RETURN_NOT_OK(res) if (!(res).ok()) return (res)
19
20 namespace skiagm {
21 namespace verifiers {
22
VerifierResult()23 VerifierResult::VerifierResult() : VerifierResult(Code::kOk, SkString("Ok")) {}
24
VerifierResult(VerifierResult::Code code,const SkString & msg)25 VerifierResult::VerifierResult(VerifierResult::Code code, const SkString& msg) :
26 fCode(code), fMessage(msg) {}
27
ok() const28 bool VerifierResult::ok() const {
29 return fCode == Code::kOk;
30 }
31
message() const32 const SkString& VerifierResult::message() const {
33 return fMessage;
34 }
35
Ok()36 VerifierResult VerifierResult::Ok() {
37 return VerifierResult(Code::kOk, SkString("Ok"));
38 }
39
Fail(const SkString & msg)40 VerifierResult VerifierResult::Fail(const SkString& msg) {
41 return VerifierResult(Code::kFail, msg);
42 }
43
GMVerifier(InputType inputType)44 GMVerifier::GMVerifier(InputType inputType) : fInputType(inputType) {}
45
~GMVerifier()46 GMVerifier::~GMVerifier() {}
47
needsGoldImage() const48 bool GMVerifier::needsGoldImage() const {
49 return fInputType == InputType::kGoldImageRequired;
50 }
51
verify(const SkBitmap & gold,const SkBitmap & actual)52 VerifierResult GMVerifier::verify(const SkBitmap& gold, const SkBitmap& actual) {
53 // Call into specific implementation.
54 return verifyWithGold(actual.bounds(), gold, actual);
55 }
56
verify(const SkBitmap & actual)57 VerifierResult GMVerifier::verify(const SkBitmap& actual) {
58 // Call into specific implementation.
59 return verify(actual.bounds(), actual);
60 }
61
RenderGoldBmp(skiagm::GM * gm,const SkColorInfo & colorInfo)62 SkBitmap GMVerifier::RenderGoldBmp(skiagm::GM* gm, const SkColorInfo& colorInfo) {
63 SkASSERT(gm);
64
65 // Call into the GM instance to get the initial image.
66 const SkISize size = gm->getISize();
67 SkBitmap goldBmp;
68 goldBmp.allocPixels(SkImageInfo::Make(size, colorInfo));
69 SkCanvas canvas(goldBmp);
70
71 if (gm->gpuSetup(nullptr, &canvas) == DrawResult::kOk) {
72 gm->draw(&canvas);
73 }
74
75 // Convert into common verifier colorspace.
76 SkBitmap goldVerifierBmp;
77 goldVerifierBmp.allocPixels(SkImageInfo::Make(size, VerifierColorInfo()));
78 SkCanvas verifierCanvas(goldVerifierBmp);
79 verifierCanvas.drawImage(goldBmp.asImage(), 0, 0);
80
81 return goldVerifierBmp;
82 }
83
VerifierColorInfo()84 SkColorInfo GMVerifier::VerifierColorInfo() {
85 return SkColorInfo(
86 kRGBA_F16_SkColorType, kPremul_SkAlphaType,
87 SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020));
88 }
89
makeError(const SkString & msg) const90 VerifierResult GMVerifier::makeError(const SkString& msg) const {
91 return VerifierResult::Fail(SkStringPrintf("[%s] %s", name().c_str(), msg.c_str()));
92 }
93
VerifierList(GM * gm)94 VerifierList::VerifierList(GM* gm) : fGM(gm), fFailedVerifier(nullptr) {}
95
add(std::unique_ptr<GMVerifier> verifier)96 void VerifierList::add(std::unique_ptr<GMVerifier> verifier) {
97 fVerifiers.push_back(std::move(verifier));
98 }
99
needsGoldImage() const100 bool VerifierList::needsGoldImage() const {
101 for (const auto& v : fVerifiers) {
102 if (v->needsGoldImage()) {
103 return true;
104 }
105 }
106
107 return false;
108 }
109
verifyAll(const SkColorInfo & colorInfo,const SkBitmap & actual)110 VerifierResult VerifierList::verifyAll(const SkColorInfo& colorInfo, const SkBitmap& actual) {
111 // Render the golden image if any verifiers need it.
112 SkBitmap goldBmp;
113 if (needsGoldImage()) {
114 goldBmp = GMVerifier::RenderGoldBmp(fGM, colorInfo);
115 }
116
117 for (const auto& v : fVerifiers) {
118 fFailedVerifier = v.get();
119 if (v->needsGoldImage()) {
120 RETURN_NOT_OK(v->verify(goldBmp, actual));
121 } else {
122 RETURN_NOT_OK(v->verify(actual));
123 }
124 }
125
126 fFailedVerifier = nullptr;
127 return VerifierResult::Ok();
128 }
129
130 } // namespace verifiers
131 } // namespace skiagm
132