| /* |
| * Copyright 2019 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "gm/gm.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkYUVAIndex.h" |
| #include "include/core/SkYUVASizeInfo.h" |
| #include "src/core/SkCachedData.h" |
| #include "src/image/SkImage_Base.h" |
| #include "tools/Resources.h" |
| #include "tools/ToolUtils.h" |
| |
| // Modeled on the layout test css3/blending/background-blend-mode-image-image.html to reproduce |
| // skbug.com/9619 |
| DEF_SIMPLE_GM_CAN_FAIL(ducky_yuv_blend, canvas, errorMsg, 560, 1130) { |
| sk_sp<SkImage> duckyBG = GetResourceAsImage("ducky.png"); |
| sk_sp<SkImage> duckyFG[2] = {GetResourceAsImage("ducky.jpg"), nullptr}; |
| if (!duckyFG[0] || !duckyBG) { |
| *errorMsg = "Image(s) failed to load."; |
| return skiagm::DrawResult::kFail; |
| } |
| |
| // If we're on the GPU we do a second round of draws where the source image is YUV planes. |
| // Otherwise we just draw the original again, |
| if (auto* context = canvas->getGrContext()) { |
| SkYUVASizeInfo info; |
| SkYUVAIndex indices[4]; |
| SkYUVColorSpace yuvColorSpace; |
| const void* planes[4]; |
| auto data = as_IB(duckyFG[0])->getPlanes(&info, indices, &yuvColorSpace, planes); |
| SkPixmap pixmaps[4]; |
| for (int i = 0; i < 4; ++i) { |
| if (indices[i].fIndex >= 0) { |
| pixmaps[i].reset( |
| SkImageInfo::MakeA8(info.fSizes[i]), planes[i], info.fWidthBytes[i]); |
| } |
| } |
| duckyFG[1] = SkImage::MakeFromYUVAPixmaps(context, |
| yuvColorSpace, |
| pixmaps, |
| indices, |
| duckyFG[0]->dimensions(), |
| kTopLeft_GrSurfaceOrigin, |
| true); |
| } else { |
| duckyFG[1] = duckyFG[0]; |
| } |
| |
| static constexpr int kNumPerRow = 4; |
| static constexpr int kPad = 10; |
| static constexpr auto kDstRect = SkRect::MakeWH(130, 130); |
| int rowCnt = 0; |
| canvas->translate(kPad, kPad); |
| canvas->save(); |
| auto newRow = [&] { |
| canvas->restore(); |
| canvas->translate(0, kDstRect.height() + kPad); |
| canvas->save(); |
| rowCnt = 0; |
| }; |
| ToolUtils::draw_checkerboard( |
| canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, (kDstRect.height() + kPad)/5); |
| for (auto& fg : duckyFG) { |
| for (int bm = static_cast<int>(SkBlendMode::kLastCoeffMode) + 1; |
| bm < static_cast<int>(SkBlendMode::kLastMode); |
| ++bm) { |
| auto mode = static_cast<SkBlendMode>(bm); |
| SkPaint paint; |
| paint.setFilterQuality(kMedium_SkFilterQuality); |
| canvas->drawImageRect(duckyBG, kDstRect, &paint); |
| paint.setBlendMode(mode); |
| canvas->drawImageRect(fg, kDstRect, &paint); |
| canvas->translate(kDstRect.width() + kPad, 0); |
| if (++rowCnt == kNumPerRow) { |
| newRow(); |
| } |
| } |
| // Force a new row between the two foreground images |
| newRow(); |
| } |
| canvas->restore(); |
| return skiagm::DrawResult::kOk; |
| } |