Handle F16Norm clamping in SkPaint->GrPaint conversion.
Previously this clamping was inserted by the program builder. Adds GrSaturateProcessor to handle saturating in the fragment shader. Clamp the GrPaint color rather than using a fp when possible. Has to be plumbed through GrTextureOp because that skips SkPaint conversion. Removes a usage of GrPixelConfig. Bug: skia:6718 Change-Id: Ifa6544496d34677f17e797433e6ef3a97be5c2b2 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/242558 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
ea869c6c5d
commit
f19f9caab2
@ -388,6 +388,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/generated/GrRectBlurEffect.h",
|
||||
"$_src/gpu/effects/generated/GrRRectBlurEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrRRectBlurEffect.h",
|
||||
"$_src/gpu/effects/generated/GrSaturateProcessor.cpp",
|
||||
"$_src/gpu/effects/generated/GrSaturateProcessor.h",
|
||||
"$_src/gpu/effects/generated/GrSimpleTextureEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrSimpleTextureEffect.h",
|
||||
|
||||
|
@ -55,6 +55,7 @@ skia_gpu_processor_sources = [
|
||||
"$_src/gpu/effects/GrPremulInputFragmentProcessor.fp",
|
||||
"$_src/gpu/effects/GrRectBlurEffect.fp",
|
||||
"$_src/gpu/effects/GrRRectBlurEffect.fp",
|
||||
"$_src/gpu/effects/GrSaturateProcessor.fp",
|
||||
"$_src/gpu/effects/GrSimpleTextureEffect.fp",
|
||||
"$_src/gpu/gradients/GrDualIntervalGradientColorizer.fp",
|
||||
"$_src/gpu/gradients/GrSingleIntervalGradientColorizer.fp",
|
||||
|
@ -57,7 +57,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
|
||||
* manually adjusted.
|
||||
*/
|
||||
#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
|
||||
static const int kFPFactoryCount = 36;
|
||||
static const int kFPFactoryCount = 37;
|
||||
static const int kGPFactoryCount = 14;
|
||||
static const int kXPFactoryCount = 4;
|
||||
#else
|
||||
|
@ -77,14 +77,12 @@ public:
|
||||
kDefaultGeoProc_ClassID,
|
||||
kDIEllipseGeometryProcessor_ClassID,
|
||||
kDisableColorXP_ClassID,
|
||||
kTwoPointConicalEffect_ClassID,
|
||||
kEllipseGeometryProcessor_ClassID,
|
||||
kEllipticalRRectEffect_ClassID,
|
||||
kGP_ClassID,
|
||||
kVertexColorSpaceBenchGP_ClassID,
|
||||
kGrAARectEffect_ClassID,
|
||||
kGrAlphaThresholdFragmentProcessor_ClassID,
|
||||
kGrArithmeticFP_ClassID,
|
||||
kGrBicubicEffect_ClassID,
|
||||
kGrBitmapTextGeoProc_ClassID,
|
||||
kGrBlurredEdgeFragmentProcessor_ClassID,
|
||||
@ -107,16 +105,12 @@ public:
|
||||
kGrDistanceFieldA8TextGeoProc_ClassID,
|
||||
kGrDistanceFieldLCDTextGeoProc_ClassID,
|
||||
kGrDistanceFieldPathGeoProc_ClassID,
|
||||
kGrDitherEffect_ClassID,
|
||||
kGrDualIntervalGradientColorizer_ClassID,
|
||||
kGrEllipseEffect_ClassID,
|
||||
kGrFillRRectOp_Processor_ClassID,
|
||||
kGrGaussianConvolutionFragmentProcessor_ClassID,
|
||||
kGrGSCoverageProcessor_ClassID,
|
||||
kGrImprovedPerlinNoiseEffect_ClassID,
|
||||
kGrIncrDecrWindingCountXP_ClassID,
|
||||
kGrLightingEffect_ClassID,
|
||||
kGrLinearGradient_ClassID,
|
||||
kGrLinearGradientLayout_ClassID,
|
||||
kGrLumaColorFilterEffect_ClassID,
|
||||
kGrMagnifierEffect_ClassID,
|
||||
@ -124,47 +118,38 @@ public:
|
||||
kGrMeshTestProcessor_ClassID,
|
||||
kGrMorphologyEffect_ClassID,
|
||||
kGrMixerEffect_ClassID,
|
||||
kGrOverdrawFragmentProcessor_ClassID,
|
||||
kGrOverrideInputFragmentProcessor_ClassID,
|
||||
kGrPathProcessor_ClassID,
|
||||
kGrPerlinNoise2Effect_ClassID,
|
||||
kGrPipelineDynamicStateTestProcessor_ClassID,
|
||||
kGrPremulInputFragmentProcessor_ClassID,
|
||||
kGrQuadEffect_ClassID,
|
||||
kGrRadialGradient_ClassID,
|
||||
kGrRadialGradientLayout_ClassID,
|
||||
kGrRectBlurEffect_ClassID,
|
||||
kGrRRectBlurEffect_ClassID,
|
||||
kGrRRectShadowGeoProc_ClassID,
|
||||
kGrResolveWindingCountXP_ClassID,
|
||||
kGrSimpleTextureEffect_ClassID,
|
||||
kGrSingleIntervalGradientColorizer_ClassID,
|
||||
kGrSkSLFP_ClassID,
|
||||
kGrSpecularLightingEffect_ClassID,
|
||||
kGrSRGBEffect_ClassID,
|
||||
kGrSampleMaskProcessor_ClassID,
|
||||
kGrSweepGradient_ClassID,
|
||||
kGrSaturateProcessor_ClassID,
|
||||
kGrSweepGradientLayout_ClassID,
|
||||
kGrTextureDomainEffect_ClassID,
|
||||
kGrTextureGradientColorizer_ClassID,
|
||||
kGrTiledGradientEffect_ClassID,
|
||||
kGrTwoPointConicalGradientLayout_ClassID,
|
||||
kGrUnpremulInputFragmentProcessor_ClassID,
|
||||
kGrUnrolledBinaryGradientColorizer_ClassID,
|
||||
kGrVSCoverageProcessor_ClassID,
|
||||
kGrYUVtoRGBEffect_ClassID,
|
||||
kHighContrastFilterEffect_ClassID,
|
||||
kInstanceProcessor_ClassID,
|
||||
kLatticeGP_ClassID,
|
||||
kLumaColorFilterEffect_ClassID,
|
||||
kMSAAQuadProcessor_ClassID,
|
||||
kPDLCDXferProcessor_ClassID,
|
||||
kPorterDuffXferProcessor_ClassID,
|
||||
kPremulFragmentProcessor_ClassID,
|
||||
kQuadEdgeEffect_ClassID,
|
||||
kQuadPerEdgeAAGeometryProcessor_ClassID,
|
||||
kReplaceInputFragmentProcessor_ClassID,
|
||||
kRRectsGaussianEdgeFP_ClassID,
|
||||
kSampleLocationsTestProcessor_ClassID,
|
||||
kSeriesFragmentProcessor_ClassID,
|
||||
kShaderPDXferProcessor_ClassID,
|
||||
@ -172,7 +157,6 @@ public:
|
||||
kFwidthSquircleTestProcessor_ClassID,
|
||||
kSwizzleFragmentProcessor_ClassID,
|
||||
kTestFP_ClassID,
|
||||
kTextureGeometryProcessor_ClassID,
|
||||
kFlatNormalsFP_ClassID,
|
||||
kMappedNormalsFP_ClassID,
|
||||
kLightingFP_ClassID,
|
||||
|
@ -261,7 +261,5 @@ bool GrProgramDesc::Build(
|
||||
SkASSERT(header->processorFeatures() == processorFeatures); // Ensure enough bits.
|
||||
header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
|
||||
header->fHasPointSize = hasPointSize ? 1 : 0;
|
||||
header->fClampBlendInput =
|
||||
GrClampType::kManual == GrPixelConfigClampType(renderTarget->config()) ? 1 : 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -112,8 +112,7 @@ public:
|
||||
uint8_t fProcessorFeatures : 1;
|
||||
bool fSnapVerticesToPixelCenters : 1;
|
||||
bool fHasPointSize : 1;
|
||||
bool fClampBlendInput : 1;
|
||||
uint8_t fPad : 2;
|
||||
uint8_t fPad : 3;
|
||||
};
|
||||
GR_STATIC_ASSERT(sizeof(KeyHeader) == 6);
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/GrRenderTargetContext.h"
|
||||
|
||||
#include "include/core/SkDrawable.h"
|
||||
#include "include/gpu/GrBackendSemaphore.h"
|
||||
#include "include/private/GrRecordingContext.h"
|
||||
@ -32,7 +34,6 @@
|
||||
#include "src/gpu/GrPathRenderer.h"
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
#include "src/gpu/GrRenderTarget.h"
|
||||
#include "src/gpu/GrRenderTargetContext.h"
|
||||
#include "src/gpu/GrRenderTargetContextPriv.h"
|
||||
#include "src/gpu/GrResourceProvider.h"
|
||||
#include "src/gpu/GrStencilAttachment.h"
|
||||
@ -676,6 +677,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_IF_ABANDONED
|
||||
SkDEBUGCODE(this->validate();)
|
||||
SkASSERT(proxy);
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexturedQuad", fContext);
|
||||
|
||||
AutoCheckFlush acf(this->drawingManager());
|
||||
@ -693,12 +695,15 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
|
||||
const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
|
||||
: clip;
|
||||
GrAAType aaType = this->chooseAAType(aa);
|
||||
auto clampType = GrColorTypeClampType(this->colorSpaceInfo().colorType());
|
||||
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
|
||||
: GrTextureOp::Saturate::kNo;
|
||||
// Use the provided domain, although hypothetically we could detect that the cropped local
|
||||
// quad is sufficiently inside the domain and the constraint could be dropped.
|
||||
this->addDrawOp(finalClip, GrTextureOp::Make(fContext, std::move(proxy),
|
||||
std::move(textureXform), filter, color,
|
||||
blendMode, aaType, edgeFlags,
|
||||
croppedDeviceQuad, croppedLocalQuad, domain));
|
||||
this->addDrawOp(finalClip,
|
||||
GrTextureOp::Make(fContext, std::move(proxy), std::move(textureXform),
|
||||
filter, color, saturate, blendMode, aaType, edgeFlags,
|
||||
croppedDeviceQuad, croppedLocalQuad, domain));
|
||||
}
|
||||
}
|
||||
|
||||
@ -956,8 +961,11 @@ void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetE
|
||||
// Can use a single op, avoiding GrPaint creation, and can batch across proxies
|
||||
AutoCheckFlush acf(this->drawingManager());
|
||||
GrAAType aaType = this->chooseAAType(aa);
|
||||
auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, aaType, constraint, viewMatrix,
|
||||
std::move(texXform));
|
||||
auto clampType = GrColorTypeClampType(this->colorSpaceInfo().colorType());
|
||||
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
|
||||
: GrTextureOp::Saturate::kNo;
|
||||
auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, saturate, aaType, constraint,
|
||||
viewMatrix, std::move(texXform));
|
||||
this->addDrawOp(clip, std::move(op));
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/SkGr.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkColorFilter.h"
|
||||
#include "include/core/SkData.h"
|
||||
@ -33,16 +35,15 @@
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
#include "src/gpu/GrTextureProxy.h"
|
||||
#include "src/gpu/GrXferProcessor.h"
|
||||
#include "src/gpu/SkGr.h"
|
||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||
#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
|
||||
#include "src/gpu/effects/GrSkSLFP.h"
|
||||
#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
|
||||
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
|
||||
#include "src/gpu/effects/generated/GrSaturateProcessor.h"
|
||||
#include "src/image/SkImage_Base.h"
|
||||
#include "src/shaders/SkShaderBase.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
GR_FP_SRC_STRING SKSL_DITHER_SRC = R"(
|
||||
// This controls the range of values added to color channels
|
||||
layout(key) in int rangeType;
|
||||
@ -82,7 +83,6 @@ void main(float x, float y, inout half4 color) {
|
||||
color = half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
|
||||
}
|
||||
)";
|
||||
#endif
|
||||
|
||||
GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) {
|
||||
GrSurfaceDesc desc;
|
||||
@ -472,6 +472,17 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (GrColorTypeClampType(colorSpaceInfo.colorType()) == GrClampType::kManual) {
|
||||
if (grPaint->numColorFragmentProcessors()) {
|
||||
grPaint->addColorFragmentProcessor(GrSaturateProcessor::Make());
|
||||
} else {
|
||||
auto color = grPaint->getColor4f();
|
||||
grPaint->setColor4f({SkTPin(color.fR, 0.f, 1.f),
|
||||
SkTPin(color.fG, 0.f, 1.f),
|
||||
SkTPin(color.fB, 0.f, 1.f),
|
||||
SkTPin(color.fA, 0.f, 1.f)});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
25
src/gpu/effects/GrSaturateProcessor.fp
Normal file
25
src/gpu/effects/GrSaturateProcessor.fp
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
@optimizationFlags {
|
||||
kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag
|
||||
}
|
||||
|
||||
void main() { sk_OutColor = saturate(sk_InColor); }
|
||||
|
||||
@class {
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
|
||||
return {SkTPin(input.fR, 0.f, 1.f),
|
||||
SkTPin(input.fG, 0.f, 1.f),
|
||||
SkTPin(input.fB, 0.f, 1.f),
|
||||
SkTPin(input.fA, 0.f, 1.f)};
|
||||
}
|
||||
}
|
||||
|
||||
@test(d) { return GrSaturateProcessor::Make(); }
|
54
src/gpu/effects/generated/GrSaturateProcessor.cpp
Normal file
54
src/gpu/effects/generated/GrSaturateProcessor.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**************************************************************************************************
|
||||
*** This file was autogenerated from GrSaturateProcessor.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#include "GrSaturateProcessor.h"
|
||||
|
||||
#include "include/gpu/GrTexture.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
|
||||
#include "src/sksl/SkSLCPP.h"
|
||||
#include "src/sksl/SkSLUtil.h"
|
||||
class GrGLSLSaturateProcessor : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLSaturateProcessor() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrSaturateProcessor& _outer = args.fFp.cast<GrSaturateProcessor>();
|
||||
(void)_outer;
|
||||
fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);\n", args.fOutputColor,
|
||||
args.fInputColor);
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {}
|
||||
};
|
||||
GrGLSLFragmentProcessor* GrSaturateProcessor::onCreateGLSLInstance() const {
|
||||
return new GrGLSLSaturateProcessor();
|
||||
}
|
||||
void GrSaturateProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {}
|
||||
bool GrSaturateProcessor::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrSaturateProcessor& that = other.cast<GrSaturateProcessor>();
|
||||
(void)that;
|
||||
return true;
|
||||
}
|
||||
GrSaturateProcessor::GrSaturateProcessor(const GrSaturateProcessor& src)
|
||||
: INHERITED(kGrSaturateProcessor_ClassID, src.optimizationFlags()) {}
|
||||
std::unique_ptr<GrFragmentProcessor> GrSaturateProcessor::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrSaturateProcessor(*this));
|
||||
}
|
||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSaturateProcessor);
|
||||
#if GR_TEST_UTILS
|
||||
std::unique_ptr<GrFragmentProcessor> GrSaturateProcessor::TestCreate(GrProcessorTestData* d) {
|
||||
return GrSaturateProcessor::Make();
|
||||
}
|
||||
#endif
|
41
src/gpu/effects/generated/GrSaturateProcessor.h
Normal file
41
src/gpu/effects/generated/GrSaturateProcessor.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**************************************************************************************************
|
||||
*** This file was autogenerated from GrSaturateProcessor.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#ifndef GrSaturateProcessor_DEFINED
|
||||
#define GrSaturateProcessor_DEFINED
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include "src/gpu/GrCoordTransform.h"
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
class GrSaturateProcessor : public GrFragmentProcessor {
|
||||
public:
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
|
||||
return {SkTPin(input.fR, 0.f, 1.f), SkTPin(input.fG, 0.f, 1.f), SkTPin(input.fB, 0.f, 1.f),
|
||||
SkTPin(input.fA, 0.f, 1.f)};
|
||||
}
|
||||
static std::unique_ptr<GrFragmentProcessor> Make() {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrSaturateProcessor());
|
||||
}
|
||||
GrSaturateProcessor(const GrSaturateProcessor& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "SaturateProcessor"; }
|
||||
|
||||
private:
|
||||
GrSaturateProcessor()
|
||||
: INHERITED(kGrSaturateProcessor_ClassID,
|
||||
(OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag) {}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
#endif
|
@ -255,16 +255,7 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
|
||||
SkASSERT(dstTexture->texturePriv().textureType() != GrTextureType::kExternal);
|
||||
}
|
||||
|
||||
SkString finalInColor;
|
||||
if (colorIn.size()) {
|
||||
if (this->desc()->header().fClampBlendInput) {
|
||||
finalInColor.printf("saturate(%s)", colorIn.c_str());
|
||||
} else {
|
||||
finalInColor = colorIn;
|
||||
}
|
||||
} else {
|
||||
finalInColor = "float4(1)";
|
||||
}
|
||||
SkString finalInColor = colorIn.size() ? colorIn : SkString("float4(1)");
|
||||
|
||||
GrGLSLXferProcessor::EmitArgs args(&fFS,
|
||||
this->uniformHandler(),
|
||||
|
@ -850,6 +850,7 @@ int VertexSpec::localDimensionality() const {
|
||||
|
||||
class QuadPerEdgeAAGeometryProcessor : public GrGeometryProcessor {
|
||||
public:
|
||||
using Saturate = GrTextureOp::Saturate;
|
||||
|
||||
static sk_sp<GrGeometryProcessor> Make(const VertexSpec& spec) {
|
||||
return sk_sp<QuadPerEdgeAAGeometryProcessor>(new QuadPerEdgeAAGeometryProcessor(spec));
|
||||
@ -859,33 +860,36 @@ public:
|
||||
GrTextureType textureType,
|
||||
const GrSamplerState& samplerState,
|
||||
const GrSwizzle& swizzle, uint32_t extraSamplerKey,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||
Saturate saturate) {
|
||||
return sk_sp<QuadPerEdgeAAGeometryProcessor>(new QuadPerEdgeAAGeometryProcessor(
|
||||
vertexSpec, caps, textureType, samplerState, swizzle, extraSamplerKey,
|
||||
std::move(textureColorSpaceXform)));
|
||||
std::move(textureColorSpaceXform), saturate));
|
||||
}
|
||||
|
||||
const char* name() const override { return "QuadPerEdgeAAGeometryProcessor"; }
|
||||
|
||||
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
|
||||
// texturing, device-dimensions are single bit flags
|
||||
uint32_t x = fTexDomain.isInitialized() ? 0 : 1;
|
||||
x |= fSampler.isInitialized() ? 0 : 2;
|
||||
x |= fNeedsPerspective ? 0 : 4;
|
||||
uint32_t x = (fTexDomain.isInitialized() ? 0 : 0x1)
|
||||
| (fSampler.isInitialized() ? 0 : 0x2)
|
||||
| (fNeedsPerspective ? 0 : 0x4)
|
||||
| (fSaturate == Saturate::kNo ? 0 : 0x8);
|
||||
// local coords require 2 bits (3 choices), 00 for none, 01 for 2d, 10 for 3d
|
||||
if (fLocalCoord.isInitialized()) {
|
||||
x |= kFloat3_GrVertexAttribType == fLocalCoord.cpuType() ? 8 : 16;
|
||||
x |= kFloat3_GrVertexAttribType == fLocalCoord.cpuType() ? 0x10 : 0x20;
|
||||
}
|
||||
// similar for colors, 00 for none, 01 for bytes, 10 for half-floats
|
||||
if (fColor.isInitialized()) {
|
||||
x |= kUByte4_norm_GrVertexAttribType == fColor.cpuType() ? 32 : 64;
|
||||
x |= kUByte4_norm_GrVertexAttribType == fColor.cpuType() ? 0x40 : 0x80;
|
||||
}
|
||||
// and coverage mode, 00 for none, 01 for withposition, 10 for withcolor, 11 for
|
||||
// position+geomdomain
|
||||
SkASSERT(!fGeomDomain.isInitialized() || fCoverageMode == CoverageMode::kWithPosition);
|
||||
if (fCoverageMode != CoverageMode::kNone) {
|
||||
x |= fGeomDomain.isInitialized() ?
|
||||
384 : (CoverageMode::kWithPosition == fCoverageMode ? 128 : 256);
|
||||
x |= fGeomDomain.isInitialized()
|
||||
? 0x300
|
||||
: (CoverageMode::kWithPosition == fCoverageMode ? 0x100 : 0x200);
|
||||
}
|
||||
|
||||
b->add32(GrColorSpaceXform::XformKey(fTextureColorSpaceXform.get()));
|
||||
@ -990,6 +994,14 @@ public:
|
||||
args.fOutputColor, args.fTexSamplers[0], "texCoord", kFloat2_GrSLType,
|
||||
&fTextureColorSpaceXformHelper);
|
||||
args.fFragBuilder->codeAppend(";");
|
||||
if (gp.fSaturate == Saturate::kYes) {
|
||||
args.fFragBuilder->codeAppendf("%s = saturate(%s);",
|
||||
args.fOutputColor, args.fOutputColor);
|
||||
}
|
||||
} else {
|
||||
// Saturate is only intended for use with a proxy to account for the fact
|
||||
// that GrTextureOp skips SkPaint conversion, which normally handles this.
|
||||
SkASSERT(gp.fSaturate == Saturate::kNo);
|
||||
}
|
||||
|
||||
// And lastly, output the coverage calculation code
|
||||
@ -1056,8 +1068,10 @@ private:
|
||||
const GrSamplerState& samplerState,
|
||||
const GrSwizzle& swizzle,
|
||||
uint32_t extraSamplerKey,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform)
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||
Saturate saturate)
|
||||
: INHERITED(kQuadPerEdgeAAGeometryProcessor_ClassID)
|
||||
, fSaturate(saturate)
|
||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||
, fSampler(textureType, samplerState, swizzle, extraSamplerKey) {
|
||||
SkASSERT(spec.hasLocalCoords());
|
||||
@ -1122,6 +1136,8 @@ private:
|
||||
// The positions attribute may have coverage built into it, so float3 is an ambiguous type
|
||||
// and may mean 2d with coverage, or 3d with no coverage
|
||||
bool fNeedsPerspective;
|
||||
// Should saturate() be called on the color? Only relevant when created with a texture.
|
||||
Saturate fSaturate = Saturate::kNo;
|
||||
CoverageMode fCoverageMode;
|
||||
|
||||
// Color space will be null and fSampler.isInitialized() returns false when the GP is configured
|
||||
@ -1140,9 +1156,11 @@ sk_sp<GrGeometryProcessor> MakeTexturedProcessor(const VertexSpec& spec, const G
|
||||
GrTextureType textureType,
|
||||
const GrSamplerState& samplerState,
|
||||
const GrSwizzle& swizzle, uint32_t extraSamplerKey,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||
Saturate saturate) {
|
||||
return QuadPerEdgeAAGeometryProcessor::Make(spec, caps, textureType, samplerState, swizzle,
|
||||
extraSamplerKey, std::move(textureColorSpaceXform));
|
||||
extraSamplerKey, std::move(textureColorSpaceXform),
|
||||
saturate);
|
||||
}
|
||||
|
||||
} // namespace GrQuadPerEdgeAA
|
||||
|
@ -16,12 +16,14 @@
|
||||
#include "src/gpu/GrSamplerState.h"
|
||||
#include "src/gpu/geometry/GrQuad.h"
|
||||
#include "src/gpu/ops/GrMeshDrawOp.h"
|
||||
#include "src/gpu/ops/GrTextureOp.h"
|
||||
|
||||
class GrCaps;
|
||||
class GrColorSpaceXform;
|
||||
class GrShaderCaps;
|
||||
|
||||
namespace GrQuadPerEdgeAA {
|
||||
using Saturate = GrTextureOp::Saturate;
|
||||
|
||||
enum class Domain : bool { kNo = false, kYes = true };
|
||||
enum class ColorType { kNone, kByte, kHalf, kLast = kHalf };
|
||||
@ -84,7 +86,7 @@ namespace GrQuadPerEdgeAA {
|
||||
sk_sp<GrGeometryProcessor> MakeTexturedProcessor(
|
||||
const VertexSpec& spec, const GrShaderCaps& caps, GrTextureType textureType,
|
||||
const GrSamplerState& samplerState, const GrSwizzle& swizzle, uint32_t extraSamplerKey,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform);
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform, Saturate saturate);
|
||||
|
||||
// Fill vertices with the vertex data needed to represent the given quad. The device position,
|
||||
// local coords, vertex color, domain, and edge coefficients will be written and/or computed
|
||||
|
@ -5,8 +5,8 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/ops/GrTextureOp.h"
|
||||
#include <new>
|
||||
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkPoint3.h"
|
||||
#include "include/gpu/GrTexture.h"
|
||||
@ -31,6 +31,7 @@
|
||||
#include "src/gpu/GrTextureProxy.h"
|
||||
#include "src/gpu/SkGr.h"
|
||||
#include "src/gpu/effects/GrTextureDomain.h"
|
||||
#include "src/gpu/effects/generated/GrSaturateProcessor.h"
|
||||
#include "src/gpu/geometry/GrQuad.h"
|
||||
#include "src/gpu/geometry/GrQuadBuffer.h"
|
||||
#include "src/gpu/geometry/GrQuadUtils.h"
|
||||
@ -38,6 +39,7 @@
|
||||
#include "src/gpu/ops/GrFillRectOp.h"
|
||||
#include "src/gpu/ops/GrMeshDrawOp.h"
|
||||
#include "src/gpu/ops/GrQuadPerEdgeAA.h"
|
||||
#include "src/gpu/ops/GrTextureOp.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -146,28 +148,31 @@ public:
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
const SkPMColor4f& color,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
GrQuadAAFlags aaFlags,
|
||||
const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad,
|
||||
const SkRect* domain) {
|
||||
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
||||
return pool->allocate<TextureOp>(
|
||||
std::move(proxy), std::move(textureXform), filter, color, aaType, aaFlags,
|
||||
deviceQuad, localQuad, domain);
|
||||
return pool->allocate<TextureOp>(std::move(proxy), std::move(textureXform), filter, color,
|
||||
saturate, aaType, aaFlags, deviceQuad, localQuad, domain);
|
||||
}
|
||||
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int cnt, GrSamplerState::Filter filter, GrAAType aaType,
|
||||
int cnt,
|
||||
GrSamplerState::Filter filter,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
|
||||
size_t size = sizeof(TextureOp) + sizeof(Proxy) * (cnt - 1);
|
||||
GrOpMemoryPool* pool = context->priv().opMemoryPool();
|
||||
void* mem = pool->allocate(size);
|
||||
return std::unique_ptr<GrDrawOp>(new (mem) TextureOp(
|
||||
set, cnt, filter, aaType, constraint, viewMatrix,
|
||||
std::move(textureColorSpaceXform)));
|
||||
return std::unique_ptr<GrDrawOp>(new (mem) TextureOp(set, cnt, filter, saturate, aaType,
|
||||
constraint, viewMatrix,
|
||||
std::move(textureColorSpaceXform)));
|
||||
}
|
||||
|
||||
~TextureOp() override {
|
||||
@ -263,13 +268,20 @@ private:
|
||||
|
||||
// dstQuad should be the geometry transformed by the view matrix. If domainRect
|
||||
// is not null it will be used to apply the strict src rect constraint.
|
||||
TextureOp(sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||
GrSamplerState::Filter filter, const SkPMColor4f& color,
|
||||
GrAAType aaType, GrQuadAAFlags aaFlags,
|
||||
const GrQuad& dstQuad, const GrQuad& srcQuad, const SkRect* domainRect)
|
||||
TextureOp(sk_sp<GrTextureProxy> proxy,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
|
||||
GrSamplerState::Filter filter,
|
||||
const SkPMColor4f& color,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
GrQuadAAFlags aaFlags,
|
||||
const GrQuad& dstQuad,
|
||||
const GrQuad& srcQuad,
|
||||
const SkRect* domainRect)
|
||||
: INHERITED(ClassID())
|
||||
, fQuads(1, true /* includes locals */)
|
||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||
, fSaturate(static_cast<unsigned>(saturate))
|
||||
, fFilter(static_cast<unsigned>(filter)) {
|
||||
// Clean up disparities between the overall aa type and edge configuration and apply
|
||||
// optimizations based on the rect and matrix when appropriate
|
||||
@ -295,13 +307,18 @@ private:
|
||||
IsZeroArea::kNo);
|
||||
fDomain = static_cast<unsigned>(domainRect != nullptr);
|
||||
}
|
||||
TextureOp(const GrRenderTargetContext::TextureSetEntry set[], int cnt,
|
||||
GrSamplerState::Filter filter, GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
|
||||
TextureOp(const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter filter,
|
||||
GrTextureOp::Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform)
|
||||
: INHERITED(ClassID())
|
||||
, fQuads(cnt, true /* includes locals */)
|
||||
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
|
||||
, fSaturate(static_cast<unsigned>(saturate))
|
||||
, fFilter(static_cast<unsigned>(filter)) {
|
||||
fProxyCnt = SkToUInt(cnt);
|
||||
SkRect bounds = SkRectPriv::MakeLargestInverted();
|
||||
@ -454,9 +471,10 @@ private:
|
||||
uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram(
|
||||
samplerState, fProxies[0].fProxy->backendFormat());
|
||||
|
||||
auto saturate = static_cast<GrTextureOp::Saturate>(fSaturate);
|
||||
sk_sp<GrGeometryProcessor> gp = GrQuadPerEdgeAA::MakeTexturedProcessor(
|
||||
vertexSpec, *target->caps().shaderCaps(), textureType, samplerState, swizzle,
|
||||
extraSamplerKey, std::move(fTextureColorSpaceXform));
|
||||
extraSamplerKey, std::move(fTextureColorSpaceXform), saturate);
|
||||
|
||||
// We'll use a dynamic state array for the GP textures when there are multiple ops.
|
||||
// Otherwise, we use fixed dynamic state to specify the single op's proxy.
|
||||
@ -554,6 +572,9 @@ private:
|
||||
}
|
||||
upgradeToCoverageAAOnMerge = true;
|
||||
}
|
||||
if (fSaturate != that->fSaturate) {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
if (fFilter != that->fFilter) {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
@ -587,12 +608,13 @@ private:
|
||||
|
||||
GrQuadBuffer<ColorDomainAndAA> fQuads;
|
||||
sk_sp<GrColorSpaceXform> fTextureColorSpaceXform;
|
||||
unsigned fSaturate : 1;
|
||||
unsigned fFilter : 2;
|
||||
unsigned fAAType : 2;
|
||||
unsigned fDomain : 1;
|
||||
unsigned fColorType : 2;
|
||||
GR_STATIC_ASSERT(GrQuadPerEdgeAA::kColorTypeCount <= 4);
|
||||
unsigned fProxyCnt : 32 - 7;
|
||||
unsigned fProxyCnt : 32 - 8;
|
||||
Proxy fProxies[1];
|
||||
|
||||
static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type does not fit in 2 bits");
|
||||
@ -609,6 +631,7 @@ std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
const SkPMColor4f& color,
|
||||
Saturate saturate,
|
||||
SkBlendMode blendMode,
|
||||
GrAAType aaType,
|
||||
GrQuadAAFlags aaFlags,
|
||||
@ -627,7 +650,7 @@ std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
|
||||
if (blendMode == SkBlendMode::kSrcOver) {
|
||||
return TextureOp::Make(context, std::move(proxy), std::move(textureXform), filter, color,
|
||||
aaType, aaFlags, deviceQuad, localQuad, domain);
|
||||
saturate, aaType, aaFlags, deviceQuad, localQuad, domain);
|
||||
} else {
|
||||
// Emulate complex blending using GrFillRectOp
|
||||
GrPaint paint;
|
||||
@ -649,6 +672,9 @@ std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
}
|
||||
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform));
|
||||
paint.addColorFragmentProcessor(std::move(fp));
|
||||
if (saturate == GrTextureOp::Saturate::kYes) {
|
||||
paint.addColorFragmentProcessor(GrSaturateProcessor::Make());
|
||||
}
|
||||
|
||||
return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
|
||||
deviceQuad, localQuad);
|
||||
@ -659,11 +685,12 @@ std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
|
||||
const GrRenderTargetContext::TextureSetEntry set[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter filter,
|
||||
Saturate saturate,
|
||||
GrAAType aaType,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
|
||||
return TextureOp::Make(context, set, cnt, filter, aaType, constraint, viewMatrix,
|
||||
return TextureOp::Make(context, set, cnt, filter, saturate, aaType, constraint, viewMatrix,
|
||||
std::move(textureColorSpaceXform));
|
||||
}
|
||||
|
||||
@ -719,8 +746,9 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
|
||||
aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
|
||||
aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
|
||||
bool useDomain = random->nextBool();
|
||||
auto saturate = random->nextBool() ? GrTextureOp::Saturate::kYes : GrTextureOp::Saturate::kNo;
|
||||
return GrTextureOp::Make(context, std::move(proxy), std::move(texXform), filter, color,
|
||||
SkBlendMode::kSrcOver, aaType, aaFlags,
|
||||
saturate, SkBlendMode::kSrcOver, aaType, aaFlags,
|
||||
GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect),
|
||||
useDomain ? &srcRect : nullptr);
|
||||
}
|
||||
|
@ -22,6 +22,12 @@ class SkMatrix;
|
||||
|
||||
namespace GrTextureOp {
|
||||
|
||||
/**
|
||||
* Controls whether saturate() is called after the texture is color-converted to ensure all
|
||||
* color values are in 0..1 range.
|
||||
*/
|
||||
enum class Saturate : bool { kNo = false, kYes = true };
|
||||
|
||||
/**
|
||||
* Creates an op that draws a sub-quadrilateral of a texture. The passed color is modulated by the
|
||||
* texture's color. 'deviceQuad' specifies the device-space coordinates to draw, using 'localQuad'
|
||||
@ -33,14 +39,15 @@ namespace GrTextureOp {
|
||||
* deconstructed into the texture, filter, modulating color, and blend mode. When blend mode is
|
||||
* src over, this will return a GrFillRectOp with a paint that samples the proxy.
|
||||
*/
|
||||
std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
|
||||
sk_sp<GrTextureProxy> proxy,
|
||||
sk_sp<GrColorSpaceXform> textureXform,
|
||||
GrSamplerState::Filter filter,
|
||||
const SkPMColor4f& color,
|
||||
SkBlendMode blendMode,
|
||||
GrAAType aaType,
|
||||
GrQuadAAFlags aaFlags,
|
||||
std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
|
||||
sk_sp<GrTextureProxy>,
|
||||
sk_sp<GrColorSpaceXform>,
|
||||
GrSamplerState::Filter,
|
||||
const SkPMColor4f&,
|
||||
Saturate,
|
||||
SkBlendMode,
|
||||
GrAAType,
|
||||
GrQuadAAFlags,
|
||||
const GrQuad& deviceQuad,
|
||||
const GrQuad& localQuad,
|
||||
const SkRect* domain = nullptr);
|
||||
@ -50,6 +57,7 @@ std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext*,
|
||||
const GrRenderTargetContext::TextureSetEntry[],
|
||||
int cnt,
|
||||
GrSamplerState::Filter,
|
||||
Saturate,
|
||||
GrAAType,
|
||||
SkCanvas::SrcRectConstraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
|
Loading…
Reference in New Issue
Block a user