3695bdb587
There was only one virtual method, so switch that to a bool stored in the base class. The derived types exist as hints for the reader, and an easy way to adjust how the new localToDevice is constructed. With this change, we don't need SkSimpleMatrixProvider. SkMatrixProvider is concrete, so we can use it directly. SkOverrideDeviceMatrixProvider no longer needs the original provider for anything, so remove that parameter. It now exists solely to inhibit the hitsPixelCenters flag. Fix a few spots (SkParticleBinding, some sites in SkRuntimeEffect) where we used SkSimpleMatrixProvider, even though the local coordinates being passed did not obey the hits-pixel-centers constraints. Most importantly, document how localToDeviceHitsPixelCenters works. Change-Id: Ibe9060bac0822d0edf52a507d390bd198d8e6dbd Reviewed-on: https://skia-review.googlesource.com/c/skia/+/482176 Reviewed-by: John Stiles <johnstiles@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
220 lines
8.4 KiB
C++
220 lines
8.4 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.
|
|
*/
|
|
|
|
// This test only works with the GPU backend.
|
|
|
|
#include "gm/gm.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkColor.h"
|
|
#include "include/core/SkFont.h"
|
|
#include "include/core/SkFontTypes.h"
|
|
#include "include/core/SkMatrix.h"
|
|
#include "include/core/SkPaint.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/SkTileMode.h"
|
|
#include "include/core/SkTypeface.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "include/effects/SkGradientShader.h"
|
|
#include "include/gpu/GrConfig.h"
|
|
#include "include/private/GrTypesPriv.h"
|
|
#include "include/private/SkColorData.h"
|
|
#include "src/core/SkCanvasPriv.h"
|
|
#include "src/core/SkMatrixProvider.h"
|
|
#include "src/gpu/GrColor.h"
|
|
#include "src/gpu/GrFragmentProcessor.h"
|
|
#include "src/gpu/GrPaint.h"
|
|
#include "src/gpu/SkGr.h"
|
|
#include "src/gpu/ops/GrOp.h"
|
|
#include "src/gpu/v1/SurfaceDrawContext_v1.h"
|
|
#include "tools/ToolUtils.h"
|
|
#include "tools/gpu/TestOps.h"
|
|
|
|
#include <utility>
|
|
|
|
namespace skiagm {
|
|
/**
|
|
* This GM directly exercises Color and ModulateRGBA.
|
|
*/
|
|
class ColorProcessor : public GpuGM {
|
|
public:
|
|
enum class TestMode {
|
|
kConstColor,
|
|
kModulateRGBA
|
|
};
|
|
|
|
ColorProcessor(TestMode mode) : fMode(mode) {
|
|
this->setBGColor(0xFFDDDDDD);
|
|
}
|
|
|
|
protected:
|
|
SkString onShortName() override {
|
|
switch (fMode) {
|
|
case TestMode::kConstColor: return SkString("const_color_processor");
|
|
case TestMode::kModulateRGBA: return SkString("modulate_rgba");
|
|
}
|
|
SkUNREACHABLE;
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(kWidth, kHeight);
|
|
}
|
|
|
|
void onOnceBeforeDraw() override {
|
|
SkColor colors[] = { 0xFFFF0000, 0x2000FF00, 0xFF0000FF};
|
|
SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(kRectSize, kRectSize) };
|
|
fShader = SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
|
|
SkTileMode::kClamp);
|
|
}
|
|
|
|
DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override {
|
|
auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
|
|
if (!sdc) {
|
|
*errorMsg = kErrorMsg_DrawSkippedGpuOnly;
|
|
return DrawResult::kSkip;
|
|
}
|
|
|
|
constexpr GrColor kColors[] = {
|
|
0xFFFFFFFF,
|
|
0xFFFF00FF,
|
|
0x80000000,
|
|
0x00000000,
|
|
};
|
|
|
|
constexpr GrColor kPaintColors[] = {
|
|
0xFFFFFFFF,
|
|
0xFF0000FF,
|
|
0x80000080,
|
|
0x00000000,
|
|
};
|
|
|
|
SkScalar y = kPad;
|
|
SkScalar x = kPad;
|
|
SkScalar maxW = 0;
|
|
for (size_t paintType = 0; paintType < SK_ARRAY_COUNT(kPaintColors) + 1; ++paintType) {
|
|
for (size_t procColor = 0; procColor < SK_ARRAY_COUNT(kColors); ++procColor) {
|
|
// translate by x,y for the canvas draws and the test target draws.
|
|
canvas->save();
|
|
canvas->translate(x, y);
|
|
|
|
// rect to draw
|
|
SkRect renderRect = SkRect::MakeXYWH(0, 0, kRectSize, kRectSize);
|
|
|
|
// Create a base-layer FP for the const color processor to draw on top of.
|
|
std::unique_ptr<GrFragmentProcessor> baseFP;
|
|
if (paintType >= SK_ARRAY_COUNT(kPaintColors)) {
|
|
GrColorInfo colorInfo;
|
|
GrFPArgs args(rContext, SkMatrixProvider(SkMatrix::I()), &colorInfo);
|
|
baseFP = as_SB(fShader)->asFragmentProcessor(args);
|
|
} else {
|
|
baseFP = GrFragmentProcessor::MakeColor(
|
|
SkPMColor4f::FromBytes_RGBA(kPaintColors[paintType]));
|
|
}
|
|
|
|
// Layer a color/modulation FP on top of the base layer, using various colors.
|
|
std::unique_ptr<GrFragmentProcessor> colorFP;
|
|
switch (fMode) {
|
|
case TestMode::kConstColor:
|
|
colorFP = GrFragmentProcessor::MakeColor(
|
|
SkPMColor4f::FromBytes_RGBA(kColors[procColor]));
|
|
break;
|
|
|
|
case TestMode::kModulateRGBA:
|
|
colorFP = GrFragmentProcessor::ModulateRGBA(
|
|
std::move(baseFP), SkPMColor4f::FromBytes_RGBA(kColors[procColor]));
|
|
break;
|
|
}
|
|
|
|
// Render the FP tree.
|
|
if (auto op = sk_gpu_test::test_ops::MakeRect(rContext,
|
|
std::move(colorFP),
|
|
renderRect.makeOffset(x, y),
|
|
renderRect,
|
|
SkMatrix::I())) {
|
|
sdc->addDrawOp(std::move(op));
|
|
}
|
|
|
|
// Draw labels for the input to the processor and the processor to the right of
|
|
// the test rect. The input label appears above the processor label.
|
|
SkFont labelFont;
|
|
labelFont.setTypeface(ToolUtils::create_portable_typeface());
|
|
labelFont.setEdging(SkFont::Edging::kAntiAlias);
|
|
labelFont.setSize(10.f);
|
|
SkPaint labelPaint;
|
|
labelPaint.setAntiAlias(true);
|
|
SkString inputLabel("Input: ");
|
|
if (paintType >= SK_ARRAY_COUNT(kPaintColors)) {
|
|
inputLabel.append("gradient");
|
|
} else {
|
|
inputLabel.appendf("0x%08x", kPaintColors[paintType]);
|
|
}
|
|
SkString procLabel;
|
|
procLabel.printf("Proc: [0x%08x]", kColors[procColor]);
|
|
|
|
SkRect inputLabelBounds;
|
|
// get the bounds of the text in order to position it
|
|
labelFont.measureText(inputLabel.c_str(), inputLabel.size(),
|
|
SkTextEncoding::kUTF8, &inputLabelBounds);
|
|
canvas->drawString(inputLabel, renderRect.fRight + kPad, -inputLabelBounds.fTop,
|
|
labelFont, labelPaint);
|
|
// update the bounds to reflect the offset we used to draw it.
|
|
inputLabelBounds.offset(renderRect.fRight + kPad, -inputLabelBounds.fTop);
|
|
|
|
SkRect procLabelBounds;
|
|
labelFont.measureText(procLabel.c_str(), procLabel.size(),
|
|
SkTextEncoding::kUTF8, &procLabelBounds);
|
|
canvas->drawString(procLabel, renderRect.fRight + kPad,
|
|
inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop,
|
|
labelFont, labelPaint);
|
|
procLabelBounds.offset(renderRect.fRight + kPad,
|
|
inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop);
|
|
|
|
labelPaint.setStrokeWidth(0);
|
|
labelPaint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawRect(renderRect, labelPaint);
|
|
|
|
canvas->restore();
|
|
|
|
// update x and y for the next test case.
|
|
SkScalar height = renderRect.height();
|
|
SkScalar width = std::max(inputLabelBounds.fRight, procLabelBounds.fRight);
|
|
maxW = std::max(maxW, width);
|
|
y += height + kPad;
|
|
if (y + height > kHeight) {
|
|
y = kPad;
|
|
x += maxW + kPad;
|
|
maxW = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return DrawResult::kOk;
|
|
}
|
|
|
|
private:
|
|
// Use this as a way of generating an input FP
|
|
sk_sp<SkShader> fShader;
|
|
TestMode fMode;
|
|
|
|
inline static constexpr SkScalar kPad = 10.f;
|
|
inline static constexpr SkScalar kRectSize = 20.f;
|
|
inline static constexpr int kWidth = 820;
|
|
inline static constexpr int kHeight = 500;
|
|
|
|
using INHERITED = GM;
|
|
};
|
|
|
|
DEF_GM(return new ColorProcessor{ColorProcessor::TestMode::kConstColor};)
|
|
DEF_GM(return new ColorProcessor{ColorProcessor::TestMode::kModulateRGBA};)
|
|
|
|
} // namespace skiagm
|