c75bc031ef
The matrices we're using can produce very slightly out of range color channels. This gives surprising results when in shader blending is used for color burn and color dodge. After this change we clamp the RGB values to 0..1 before applying premul. Adds a GM modeled on a blink layout test that shows the problem using SkImageMakeFromYUVAPixmaps. Bug: skia:9619 Change-Id: I446d39763a7f5a2f7c5f61d94d163927d851baa3 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/253879 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
89 lines
3.3 KiB
C++
89 lines
3.3 KiB
C++
/*
|
|
* 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;
|
|
}
|