5d8f55bfa8
persp_shaders_ gm expected diff (in gpu backends only), due to change from filterquality (which gpu and cpu interpreted differently for mips) to samplingoptions (which both backends interpret the same). Specifically for kMedium: - gpu treated as SkMipmapMode::kLinear - cpu treated as SkMipmapMode::kNearest Bug: skia: 7650 Change-Id: Idc53ad8d01d9c928b425c092b36191153714d347 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/343737 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
230 lines
7.2 KiB
C++
230 lines
7.2 KiB
C++
/*
|
|
* Copyright 2015 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/SkBitmap.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkColor.h"
|
|
#include "include/core/SkFilterQuality.h"
|
|
#include "include/core/SkImage.h"
|
|
#include "include/core/SkImageInfo.h"
|
|
#include "include/core/SkMatrix.h"
|
|
#include "include/core/SkPaint.h"
|
|
#include "include/core/SkPath.h"
|
|
#include "include/core/SkPoint.h"
|
|
#include "include/core/SkRect.h"
|
|
#include "include/core/SkRefCnt.h"
|
|
#include "include/core/SkScalar.h"
|
|
#include "include/core/SkShader.h"
|
|
#include "include/core/SkSize.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/core/SkSurface.h"
|
|
#include "include/core/SkTileMode.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "include/effects/SkGradientShader.h"
|
|
#include "tools/ToolUtils.h"
|
|
|
|
static sk_sp<SkImage> make_image(SkCanvas* origCanvas, int w, int h) {
|
|
SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
|
|
auto surface(ToolUtils::makeSurface(origCanvas, info));
|
|
SkCanvas* canvas = surface->getCanvas();
|
|
|
|
ToolUtils::draw_checkerboard(canvas, SK_ColorRED, SK_ColorGREEN, w / 10);
|
|
return surface->makeImageSnapshot();
|
|
}
|
|
|
|
namespace skiagm {
|
|
|
|
class PerspShadersGM : public GM {
|
|
public:
|
|
PerspShadersGM(bool doAA) : fDoAA(doAA) { }
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
SkString name;
|
|
name.printf("persp_shaders_%s",
|
|
fDoAA ? "aa" : "bw");
|
|
return name;
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(kCellSize*kNumCols, kCellSize*kNumRows);
|
|
}
|
|
|
|
void onOnceBeforeDraw() override {
|
|
fBitmap = ToolUtils::create_checkerboard_bitmap(
|
|
kCellSize, kCellSize, SK_ColorBLUE, SK_ColorYELLOW, kCellSize / 10);
|
|
fBitmap.setImmutable();
|
|
|
|
SkPoint pts1[] = {
|
|
{ 0, 0 },
|
|
{ SkIntToScalar(kCellSize), SkIntToScalar(kCellSize) }
|
|
};
|
|
SkPoint pts2[] = {
|
|
{ 0, 0 },
|
|
{ 0, SkIntToScalar(kCellSize) }
|
|
};
|
|
constexpr SkColor colors[] = {
|
|
SK_ColorRED, SK_ColorGREEN, SK_ColorRED, SK_ColorGREEN, SK_ColorRED
|
|
};
|
|
constexpr SkScalar pos[] = { 0, 0.25f, 0.5f, 0.75f, SK_Scalar1 };
|
|
|
|
fLinearGrad1 = SkGradientShader::MakeLinear(pts1, colors, pos, SK_ARRAY_COUNT(colors),
|
|
SkTileMode::kClamp);
|
|
fLinearGrad2 = SkGradientShader::MakeLinear(pts2, colors, pos, SK_ARRAY_COUNT(colors),
|
|
SkTileMode::kClamp);
|
|
|
|
fPerspMatrix.reset();
|
|
fPerspMatrix.setPerspY(SK_Scalar1 / 50);
|
|
|
|
fPath.moveTo(0, 0);
|
|
fPath.lineTo(0, SkIntToScalar(kCellSize));
|
|
fPath.lineTo(kCellSize/2.0f, kCellSize/2.0f);
|
|
fPath.lineTo(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize));
|
|
fPath.lineTo(SkIntToScalar(kCellSize), 0);
|
|
fPath.close();
|
|
}
|
|
|
|
void drawRow(SkCanvas* canvas, SkFilterQuality filterQ) {
|
|
SkPaint filterPaint;
|
|
filterPaint.setFilterQuality(filterQ);
|
|
filterPaint.setAntiAlias(fDoAA);
|
|
|
|
SkPaint pathPaint;
|
|
pathPaint.setShader(fBitmap.makeShader(SkSamplingOptions(filterQ)));
|
|
pathPaint.setAntiAlias(fDoAA);
|
|
|
|
SkPaint gradPaint1;
|
|
gradPaint1.setShader(fLinearGrad1);
|
|
gradPaint1.setAntiAlias(fDoAA);
|
|
SkPaint gradPaint2;
|
|
gradPaint2.setShader(fLinearGrad2);
|
|
gradPaint2.setAntiAlias(fDoAA);
|
|
|
|
SkRect r = SkRect::MakeWH(SkIntToScalar(kCellSize), SkIntToScalar(kCellSize));
|
|
|
|
canvas->save();
|
|
|
|
canvas->save();
|
|
canvas->concat(fPerspMatrix);
|
|
canvas->drawBitmapRect(fBitmap, r, &filterPaint);
|
|
canvas->restore();
|
|
|
|
canvas->translate(SkIntToScalar(kCellSize), 0);
|
|
canvas->save();
|
|
canvas->concat(fPerspMatrix);
|
|
canvas->drawImage(fImage.get(), 0, 0, &filterPaint);
|
|
canvas->restore();
|
|
|
|
canvas->translate(SkIntToScalar(kCellSize), 0);
|
|
canvas->save();
|
|
canvas->concat(fPerspMatrix);
|
|
canvas->drawRect(r, pathPaint);
|
|
canvas->restore();
|
|
|
|
canvas->translate(SkIntToScalar(kCellSize), 0);
|
|
canvas->save();
|
|
canvas->concat(fPerspMatrix);
|
|
canvas->drawPath(fPath, pathPaint);
|
|
canvas->restore();
|
|
|
|
canvas->translate(SkIntToScalar(kCellSize), 0);
|
|
canvas->save();
|
|
canvas->concat(fPerspMatrix);
|
|
canvas->drawRect(r, gradPaint1);
|
|
canvas->restore();
|
|
|
|
canvas->translate(SkIntToScalar(kCellSize), 0);
|
|
canvas->save();
|
|
canvas->concat(fPerspMatrix);
|
|
canvas->drawPath(fPath, gradPaint2);
|
|
canvas->restore();
|
|
|
|
canvas->restore();
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
if (!fImage || !fImage->isValid(canvas->recordingContext())) {
|
|
fImage = make_image(canvas, kCellSize, kCellSize);
|
|
}
|
|
|
|
this->drawRow(canvas, kNone_SkFilterQuality);
|
|
canvas->translate(0, SkIntToScalar(kCellSize));
|
|
this->drawRow(canvas, kLow_SkFilterQuality);
|
|
canvas->translate(0, SkIntToScalar(kCellSize));
|
|
this->drawRow(canvas, kMedium_SkFilterQuality);
|
|
canvas->translate(0, SkIntToScalar(kCellSize));
|
|
this->drawRow(canvas, kHigh_SkFilterQuality);
|
|
canvas->translate(0, SkIntToScalar(kCellSize));
|
|
}
|
|
private:
|
|
static constexpr int kCellSize = 50;
|
|
static constexpr int kNumRows = 4;
|
|
static constexpr int kNumCols = 6;
|
|
|
|
bool fDoAA;
|
|
SkPath fPath;
|
|
sk_sp<SkShader> fLinearGrad1;
|
|
sk_sp<SkShader> fLinearGrad2;
|
|
SkMatrix fPerspMatrix;
|
|
sk_sp<SkImage> fImage;
|
|
SkBitmap fBitmap;
|
|
|
|
using INHERITED = GM;
|
|
};
|
|
DEF_GM(return new PerspShadersGM(true);)
|
|
DEF_GM(return new PerspShadersGM(false);)
|
|
} // namespace skiagm
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "tools/Resources.h"
|
|
|
|
static SkPath make_path() {
|
|
SkRandom rand;
|
|
auto rand_pt = [&rand]() {
|
|
auto x = rand.nextF();
|
|
auto y = rand.nextF();
|
|
return SkPoint{x * 400, y * 400};
|
|
};
|
|
|
|
SkPath path;
|
|
for (int i = 0; i < 4; ++i) {
|
|
SkPoint pts[6];
|
|
for (auto& p : pts) {
|
|
p = rand_pt();
|
|
}
|
|
path.moveTo(pts[0]).quadTo(pts[1], pts[2]).quadTo(pts[3], pts[4]).lineTo(pts[5]);
|
|
}
|
|
return path;
|
|
}
|
|
|
|
DEF_SIMPLE_GM(perspective_clip, canvas, 800, 800) {
|
|
SkPath path = make_path();
|
|
auto shader = GetResourceAsImage("images/mandrill_128.png")
|
|
->makeShader(SkSamplingOptions(), SkMatrix::Scale(3, 3));
|
|
|
|
SkPaint paint;
|
|
paint.setColor({0.75, 0.75, 0.75, 1});
|
|
canvas->drawPath(path, paint);
|
|
|
|
// This is a crazy perspective matrix, derived from halfplanes3, to draw a shape where
|
|
// part of it is "behind" the viewer, hence showing the need for "half-plane" clipping
|
|
// when in perspective.
|
|
SkMatrix mx;
|
|
const SkScalar array[] = {
|
|
-1.7866f, 1.3357f, 273.0295f,
|
|
-1.0820f, 1.3186f, 135.5196f,
|
|
-0.0047f, -0.0015f, 2.1485f,
|
|
};
|
|
mx.set9(array);
|
|
|
|
paint.setShader(shader);
|
|
canvas->concat(mx);
|
|
canvas->drawPath(path, paint);
|
|
}
|