Skip to content

Commit

Permalink
Split GrConstColorProcessor into three separate .fp effects.
Browse files Browse the repository at this point in the history
ConstColorProcessor contained three separate InputModes with their own
unique behaviors, but every (non-test) call site simply hardcoded one of
the InputModes.

This change also allows the actual const-color processor to remove the
inputFP entirely; it is never sampled.

The GM slide has been split into three separate slides as well.

Change-Id: I2b77f4eab4d655f06e3704fb6fde8d4f8c70a075
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/301987
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
  • Loading branch information
johnstiles-google authored and Skia Commit-Bot committed Jul 13, 2020
1 parent d9800f8 commit 7c19677
Show file tree
Hide file tree
Showing 24 changed files with 598 additions and 301 deletions.
221 changes: 121 additions & 100 deletions gm/constcolorprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
#include "src/gpu/effects/generated/GrModulateAlphaEffect.h"
#include "src/gpu/effects/generated/GrModulateRGBAEffect.h"
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/ops/GrFillRectOp.h"
#include "tools/ToolUtils.h"
Expand All @@ -46,17 +48,28 @@

namespace skiagm {
/**
* This GM directly exercises GrConstColorProcessor.
* This GM directly exercises GrConstColorProcessor, GrModulateRGBAEffect and GrModulateAlphaEffect.
*/
class ConstColorProcessor : public GpuGM {
class ColorProcessor : public GpuGM {
public:
ConstColorProcessor() {
enum class TestMode {
kConstColor,
kModulateRGBA,
kModulateAlpha
};

ColorProcessor(TestMode mode) : fMode(mode) {
this->setBGColor(0xFFDDDDDD);
}

protected:
SkString onShortName() override {
return SkString("const_color_processor");
switch (fMode) {
case TestMode::kConstColor: return SkString("const_color_processor");
case TestMode::kModulateRGBA: return SkString("modulate_rgba");
case TestMode::kModulateAlpha: return SkString("modulate_alpha");
}
SkUNREACHABLE;
}

SkISize onISize() override {
Expand Down Expand Up @@ -86,106 +99,110 @@ class ConstColorProcessor : public GpuGM {
0x00000000,
};

const char* kModeStrs[] {
"kIgnore",
"kModulateRGBA",
"kModulateA",
};
static_assert(SK_ARRAY_COUNT(kModeStrs) == GrConstColorProcessor::kInputModeCnt);

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) {
for (int m = 0; m < GrConstColorProcessor::kInputModeCnt; ++m) {
// 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(context, SkSimpleMatrixProvider(SkMatrix::I()),
kHigh_SkFilterQuality, &colorInfo);
baseFP = as_SB(fShader)->asFragmentProcessor(args);
} else {
baseFP = GrConstColorProcessor::Make(
/*inputFP=*/nullptr,
SkPMColor4f::FromBytes_RGBA(kPaintColors[paintType]),
GrConstColorProcessor::InputMode::kIgnore);
}

// Layer a const-color FP on top of the base layer, using various modes/colors.
auto constColorFP = GrConstColorProcessor::Make(
std::move(baseFP), SkPMColor4f::FromBytes_RGBA(kColors[procColor]),
GrConstColorProcessor::InputMode(m));

// Render the FP tree.
if (auto op = sk_gpu_test::test_ops::MakeRect(context,
std::move(constColorFP),
renderRect.makeOffset(x, y),
renderRect,
SkMatrix::I())) {
renderTargetContext->priv().testingOnly_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;
inputLabel.set("Input: ");
if (paintType >= SK_ARRAY_COUNT(kPaintColors)) {
inputLabel.append("gradient");
} else {
inputLabel.appendf("0x%08x", kPaintColors[paintType]);
}
SkString procLabel;
procLabel.printf("Proc: [0x%08x, %s]", kColors[procColor], kModeStrs[m]);

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;
}
// 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(context, SkSimpleMatrixProvider(SkMatrix::I()),
kHigh_SkFilterQuality, &colorInfo);
baseFP = as_SB(fShader)->asFragmentProcessor(args);
} else {
baseFP = GrConstColorProcessor::Make(
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 = GrConstColorProcessor::Make(
SkPMColor4f::FromBytes_RGBA(kColors[procColor]));
break;

case TestMode::kModulateRGBA:
colorFP = GrModulateRGBAEffect::Make(
std::move(baseFP),
SkPMColor4f::FromBytes_RGBA(kColors[procColor]));
break;

case TestMode::kModulateAlpha:
colorFP = GrModulateAlphaEffect::Make(
std::move(baseFP),
SkPMColor4f::FromBytes_RGBA(kColors[procColor]));
break;
}

// Render the FP tree.
if (auto op = sk_gpu_test::test_ops::MakeRect(context,
std::move(colorFP),
renderRect.makeOffset(x, y),
renderRect,
SkMatrix::I())) {
renderTargetContext->priv().testingOnly_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;
}
}
}
Expand All @@ -194,6 +211,7 @@ class ConstColorProcessor : public GpuGM {
private:
// Use this as a way of generating an input FP
sk_sp<SkShader> fShader;
TestMode fMode;

static constexpr SkScalar kPad = 10.f;
static constexpr SkScalar kRectSize = 20.f;
Expand All @@ -203,5 +221,8 @@ class ConstColorProcessor : public GpuGM {
typedef GM INHERITED;
};

DEF_GM(return new ConstColorProcessor;)
DEF_GM(return new ColorProcessor{ColorProcessor::TestMode::kConstColor};)
DEF_GM(return new ColorProcessor{ColorProcessor::TestMode::kModulateRGBA};)
DEF_GM(return new ColorProcessor{ColorProcessor::TestMode::kModulateAlpha};)

}
4 changes: 4 additions & 0 deletions gn/gpu.gni
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ skia_gpu_sources = [
"$_src/gpu/effects/generated/GrMagnifierEffect.h",
"$_src/gpu/effects/generated/GrMixerEffect.cpp",
"$_src/gpu/effects/generated/GrMixerEffect.h",
"$_src/gpu/effects/generated/GrModulateAlphaEffect.cpp",
"$_src/gpu/effects/generated/GrModulateAlphaEffect.h",
"$_src/gpu/effects/generated/GrModulateRGBAEffect.cpp",
"$_src/gpu/effects/generated/GrModulateRGBAEffect.h",
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp",
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h",
"$_src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp",
Expand Down
2 changes: 2 additions & 0 deletions gn/sksl.gni
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ skia_gpu_processor_sources = [
"$_src/gpu/effects/GrLumaColorFilterEffect.fp",
"$_src/gpu/effects/GrMagnifierEffect.fp",
"$_src/gpu/effects/GrMixerEffect.fp",
"$_src/gpu/effects/GrModulateAlphaEffect.fp",
"$_src/gpu/effects/GrModulateRGBAEffect.fp",
"$_src/gpu/effects/GrOverrideInputFragmentProcessor.fp",
"$_src/gpu/effects/GrRGBToHSLFilterEffect.fp",
"$_src/gpu/effects/GrRRectBlurEffect.fp",
Expand Down
4 changes: 1 addition & 3 deletions src/core/SkModeColorFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ GrFPResult SkModeColorFilter::asFragmentProcessor(std::unique_ptr<GrFragmentProc

SkDEBUGCODE(const bool fpHasConstIO = !inputFP || inputFP->hasConstantOutputForConstantInput();)

auto colorFP = GrConstColorProcessor::Make(
/*inputFP=*/nullptr, SkColorToPMColor4f(fColor, dstColorInfo),
GrConstColorProcessor::InputMode::kIgnore);
auto colorFP = GrConstColorProcessor::Make(SkColorToPMColor4f(fColor, dstColorInfo));
auto xferFP = GrXfermodeFragmentProcessor::Make(
std::move(colorFP), std::move(inputFP), fMode,
GrXfermodeFragmentProcessor::ComposeBehavior::kSkModeBehavior);
Expand Down
3 changes: 1 addition & 2 deletions src/effects/imagefilters/SkArithmeticImageFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
background->getColorSpace(), background->alphaType(),
ctx.colorSpace(), kPremul_SkAlphaType);
} else {
bgFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT);
}

if (foreground) {
Expand Down
3 changes: 1 addition & 2 deletions src/effects/imagefilters/SkXfermodeImageFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilterImpl::filterImageGPU(
background->alphaType(), ctx.colorSpace(),
kPremul_SkAlphaType);
} else {
fp = GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
fp = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT);
}

if (foregroundView.asTextureProxy()) {
Expand Down
3 changes: 1 addition & 2 deletions src/gpu/GrFragmentProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
SkPMColor4f knownColor;
int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
if (leadingFPsToEliminate) {
std::unique_ptr<GrFragmentProcessor> colorFP = GrConstColorProcessor::Make(
/*inputFP=*/nullptr, knownColor, GrConstColorProcessor::InputMode::kIgnore);
std::unique_ptr<GrFragmentProcessor> colorFP = GrConstColorProcessor::Make(knownColor);
if (leadingFPsToEliminate == cnt) {
return colorFP;
}
Expand Down
2 changes: 2 additions & 0 deletions src/gpu/GrProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class GrProcessor {
kGrMatrixConvolutionEffect_ClassID,
kGrMatrixEffect_ClassID,
kGrMeshTestProcessor_ClassID,
kGrModulateAlphaEffect_ClassID,
kGrModulateRGBAEffect_ClassID,
kGrMorphologyEffect_ClassID,
kGrMixerEffect_ClassID,
kGrOverrideInputFragmentProcessor_ClassID,
Expand Down
2 changes: 1 addition & 1 deletion src/gpu/GrProcessorUnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
static const int kFPFactoryCount = 37;
static const int kFPFactoryCount = 39;
static const int kGPFactoryCount = 14;
static const int kXPFactoryCount = 4;

Expand Down
14 changes: 6 additions & 8 deletions src/gpu/SkGr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
#include "src/gpu/effects/generated/GrDitherEffect.h"
#include "src/gpu/effects/generated/GrModulateRGBAEffect.h"
#include "src/image/SkImage_Base.h"
#include "src/shaders/SkShaderBase.h"

Expand Down Expand Up @@ -262,9 +263,8 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
if (1.0f != paintAlpha) {
// No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
// color channels. It's value should be treated as the same in ANY color space.
paintFP = GrConstColorProcessor::Make(
std::move(paintFP), { paintAlpha, paintAlpha, paintAlpha, paintAlpha },
GrConstColorProcessor::InputMode::kModulateRGBA);
paintFP = GrModulateRGBAEffect::Make(
std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
}
} else {
// The shader's FP sees the paint *unpremul* color
Expand All @@ -276,8 +276,7 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
// There is a blend between the primitive color and the paint color. The blend considers
// the opaque paint color. The paint's alpha is applied to the post-blended color.
SkPMColor4f opaqueColor = origColor.makeOpaque().premul();
paintFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr, opaqueColor,
GrConstColorProcessor::InputMode::kIgnore);
paintFP = GrConstColorProcessor::Make(opaqueColor);
paintFP = GrXfermodeFragmentProcessor::Make(std::move(paintFP), /*dst=*/nullptr,
*primColorMode);
grPaint->setColor4f(opaqueColor);
Expand All @@ -287,9 +286,8 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
if (1.0f != paintAlpha) {
// No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
// color channels. It's value should be treated as the same in ANY color space.
paintFP = GrConstColorProcessor::Make(
std::move(paintFP), { paintAlpha, paintAlpha, paintAlpha, paintAlpha },
GrConstColorProcessor::InputMode::kModulateRGBA);
paintFP = GrModulateRGBAEffect::Make(
std::move(paintFP), {paintAlpha, paintAlpha, paintAlpha, paintAlpha});
}
} else {
// No shader, no primitive color.
Expand Down
Loading

0 comments on commit 7c19677

Please sign in to comment.