1 /*
2  * Copyright 2019 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 "include/core/SkCanvas.h"
10 #include "include/core/SkPaint.h"
11 #include "include/core/SkYUVAIndex.h"
12 #include "include/core/SkYUVASizeInfo.h"
13 #include "include/gpu/GrRecordingContext.h"
14 #include "src/core/SkCachedData.h"
15 #include "src/image/SkImage_Base.h"
16 #include "tools/Resources.h"
17 #include "tools/ToolUtils.h"
18 #include "tools/gpu/YUVUtils.h"
19 
20 // Modeled on the layout test css3/blending/background-blend-mode-image-image.html to reproduce
21 // skbug.com/9619
22 DEF_SIMPLE_GM_CAN_FAIL(ducky_yuv_blend, canvas, errorMsg, 560, 1130) {
23     sk_sp<SkImage> duckyBG = GetResourceAsImage("images/ducky.png");
24     sk_sp<SkImage> duckyFG[2] = {GetResourceAsImage("images/ducky.jpg"), nullptr};
25     if (!duckyFG[0] || !duckyBG) {
26         *errorMsg = "Image(s) failed to load.";
27         return skiagm::DrawResult::kFail;
28     }
29 
30     // If we're on the GPU we do a second round of draws where the source image is YUV planes.
31     // Otherwise we just draw the original again,
32     if (auto* rContext = canvas->recordingContext(); rContext && !rContext->abandoned()) {
33         auto lazyYUV = sk_gpu_test::LazyYUVImage::Make(GetResourceAsData("images/ducky.jpg"),
34                                                        GrMipmapped::kYes);
35         if (lazyYUV) {
36             duckyFG[1] = lazyYUV->refImage(rContext, sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
37         }
38         if (!duckyFG[1]) {
39             return skiagm::DrawResult::kFail;
40         }
41     } else {
42         duckyFG[1] = duckyFG[0];
43     }
44 
45     static constexpr int kNumPerRow = 4;
46     static constexpr int kPad = 10;
47     static constexpr auto kDstRect = SkRect::MakeWH(130, 130);
48     int rowCnt = 0;
49     canvas->translate(kPad, kPad);
50     canvas->save();
__anon001ebd900102null51     auto newRow = [&] {
52         canvas->restore();
53         canvas->translate(0, kDstRect.height() + kPad);
54         canvas->save();
55         rowCnt = 0;
56     };
57     ToolUtils::draw_checkerboard(
58             canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, (kDstRect.height() + kPad)/5);
59     for (auto& fg : duckyFG) {
60         for (int bm = static_cast<int>(SkBlendMode::kLastCoeffMode) + 1;
61              bm < static_cast<int>(SkBlendMode::kLastMode);
62              ++bm) {
63             auto mode = static_cast<SkBlendMode>(bm);
64             SkPaint paint;
65             paint.setFilterQuality(kMedium_SkFilterQuality);
66             canvas->drawImageRect(duckyBG, kDstRect, &paint);
67             paint.setBlendMode(mode);
68             canvas->drawImageRect(fg, kDstRect, &paint);
69             canvas->translate(kDstRect.width() + kPad, 0);
70             if (++rowCnt == kNumPerRow) {
71                 newRow();
72             }
73         }
74         // Force a new row between the two foreground images
75         newRow();
76     }
77     canvas->restore();
78     return skiagm::DrawResult::kOk;
79 }
80