diff options
author | 2016-04-13 13:56:21 -0700 | |
---|---|---|
committer | 2016-04-13 13:56:21 -0700 | |
commit | 0e3c55431b463b5575983c0c875909e08a3562bf (patch) | |
tree | 4aa76104cefbbbf35f6ba57a90bb0824ce59ed5e /src | |
parent | d3b63d3244add67b1d087123f36a418f7fd7ec0f (diff) |
Tweak distance field path renderer behavior in gamma-correct mode to match
recent changes to text rendering.
Uses linear coverage falloff. Produces results that are perceptually more
similar to L32 (raster and gpu). Smoothstep + sRGB was too soft.
Plumb the gamma-correctness via DrawPathArgs, which also paves the way for
other path rendering implementations to easily make decisions about rendering
technique based on that flag.
Fix a few typos and formatting issues from my most recent change.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1889453002
Review URL: https://codereview.chromium.org/1889453002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrDrawContext.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 3 | ||||
-rw-r--r-- | src/gpu/batches/GrAADistanceFieldPathRenderer.cpp | 19 | ||||
-rw-r--r-- | src/gpu/effects/GrDistanceFieldGeoProc.cpp | 12 |
5 files changed, 32 insertions, 6 deletions
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index 2700f56986..7418e76449 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -856,6 +856,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, args.fPath = &clipPath; args.fStroke = &stroke; args.fAntiAlias = false; + args.fGammaCorrect = false; pr->drawPath(args); } else { GrPathRenderer::StencilPathArgs args; @@ -891,6 +892,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, args.fPath = &clipPath; args.fStroke = &stroke; args.fAntiAlias = false; + args.fGammaCorrect = false; pr->drawPath(args); } } else { diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 9110b34d6f..2e4b13f03e 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -922,6 +922,7 @@ bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect, args.fPath = &path; args.fStroke = &GrStrokeInfo::FillInfo(); args.fAntiAlias = useCoverageAA; + args.fGammaCorrect = fDrawContext->isGammaCorrect(); pr->drawPath(args); return true; } @@ -1025,6 +1026,7 @@ void GrDrawContext::internalDrawPath(const GrClip& clip, args.fPath = pathPtr; args.fStroke = strokeInfoPtr; args.fAntiAlias = useCoverageAA; + args.fGammaCorrect = this->isGammaCorrect(); pr->drawPath(args); } diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index 85b3275e89..cc149061ed 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -119,6 +119,7 @@ public: * fPath the path to draw. * fStroke the stroke information (width, join, cap) * fAntiAlias true if anti-aliasing is required. + * fGammaCorrect true if gamma-correct rendering is to be used. */ struct DrawPathArgs { GrDrawTarget* fTarget; @@ -129,6 +130,7 @@ public: const SkPath* fPath; const GrStrokeInfo* fStroke; bool fAntiAlias; + bool fGammaCorrect; void validate() const { SkASSERT(fTarget); @@ -281,6 +283,7 @@ private: drawArgs.fPath = args.fPath; drawArgs.fStroke = args.fStroke; drawArgs.fAntiAlias = false; + drawArgs.fGammaCorrect = false; this->drawPath(drawArgs); } diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp index 35d1f61977..655a77127e 100644 --- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp @@ -148,8 +148,10 @@ public: }; static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix, - GrBatchAtlas* atlas, PathCache* pathCache, PathDataList* pathList) { - return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCache, pathList); + GrBatchAtlas* atlas, PathCache* pathCache, PathDataList* pathList, + bool gammaCorrect) { + return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCache, pathList, + gammaCorrect); } const char* name() const override { return "AADistanceFieldPathBatch"; } @@ -196,6 +198,7 @@ private: uint32_t flags = 0; flags |= ctm.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0; flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; + flags |= fGammaCorrect ? kGammaCorrect_DistanceFieldEffectFlag : 0; GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode); @@ -296,7 +299,8 @@ private: AADistanceFieldPathBatch(const Geometry& geometry, const SkMatrix& viewMatrix, GrBatchAtlas* atlas, - PathCache* pathCache, PathDataList* pathList) + PathCache* pathCache, PathDataList* pathList, + bool gammaCorrect) : INHERITED(ClassID()) { fBatch.fViewMatrix = viewMatrix; fGeoData.push_back(geometry); @@ -304,6 +308,7 @@ private: fAtlas = atlas; fPathCache = pathCache; fPathList = pathList; + fGammaCorrect = gammaCorrect; // Compute bounds fBounds = geometry.fPath.getBounds(); @@ -524,6 +529,7 @@ private: GrBatchAtlas* fAtlas; PathCache* fPathCache; PathDataList* fPathList; + bool fGammaCorrect; typedef GrVertexBatch INHERITED; }; @@ -562,7 +568,8 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) { SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, *args.fViewMatrix, fAtlas, - &fPathCache, &fPathList)); + &fPathCache, &fPathList, + args.fGammaCorrect)); args.fTarget->drawBatch(*args.fPipelineBuilder, batch); return true; @@ -630,6 +637,7 @@ DRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) { SkMatrix viewMatrix = GrTest::TestMatrix(random); GrColor color = GrRandomColor(random); + bool gammaCorrect = random->nextBool(); AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random)); geometry.fColor = color; @@ -640,7 +648,8 @@ DRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) { return AADistanceFieldPathBatch::Create(geometry, viewMatrix, gTestStruct.fAtlas, &gTestStruct.fPathCache, - &gTestStruct.fPathList); + &gTestStruct.fPathList, + gammaCorrect); } #endif diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp index 5dd70cd0b8..e87021e978 100644 --- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp +++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp @@ -362,6 +362,8 @@ public: bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) == kUniformScale_DistanceFieldEffectMask; bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); + bool isGammaCorrect = + SkToBool(dfTexEffect.getFlags() & kGammaCorrect_DistanceFieldEffectFlag); if (isUniformScale) { // For uniform scale, we adjust for the effect of the transformation on the distance // by using the length of the gradient of the t coordinate in the y direction. @@ -402,7 +404,15 @@ public: // this gives us a smooth step across approximately one fragment fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); } - fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); + // The smoothstep falloff compensates for the non-linear sRGB response curve. If we are + // doing gamma-correct rendering (to an sRGB or F16 buffer), then we actually want distance + // mapped linearly to coverage, so use a linear step: + if (isGammaCorrect) { + fragBuilder->codeAppend( + "float val = clamp(distance + afwidth / (2.0 * afwidth), 0.0, 1.0);"); + } else { + fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); + } fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); } |