diff options
author | Brian Osman <brianosman@google.com> | 2018-07-30 14:36:53 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-30 19:06:48 +0000 |
commit | 3ebd354730ea9590bf233deccfc24982ffe48a98 (patch) | |
tree | f9cef509dc7ccb769332cbbf740bfdbcead6dac8 | |
parent | a78b6dcb82d2f6c940e9c0a6bc14853f846344d0 (diff) |
For TextureOp + Alpha texture, xform paint color to dest color space
This is an unfortunate amount of plumbing for this, but benchmarks
confirm that we're better off doing this work in the vertex shader
(with a ubyte attribute) than using a float4 attribute.
Change-Id: I358d330ee452ea0a89cdd725019c8df2686036a0
Reviewed-on: https://skia-review.googlesource.com/144351
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
-rw-r--r-- | gm/clockwise.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 6 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.h | 2 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice_drawTexture.cpp | 18 | ||||
-rw-r--r-- | src/gpu/ops/GrTextureOp.cpp | 110 | ||||
-rw-r--r-- | src/gpu/ops/GrTextureOp.h | 3 |
6 files changed, 95 insertions, 48 deletions
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp index 0ca6e0a567..00bc47ecda 100644 --- a/gm/clockwise.cpp +++ b/gm/clockwise.cpp @@ -168,7 +168,7 @@ void ClockwiseGM::onDraw(SkCanvas* canvas) { GrSamplerState::Filter::kNearest, 0xffffffff, {0,0,100,200}, {100,0,200,200}, GrAA::kNo, SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(), - nullptr); + nullptr, nullptr); } // Draw the test to an off-screen, bottom-up render target. @@ -183,7 +183,7 @@ void ClockwiseGM::onDraw(SkCanvas* canvas) { GrSamplerState::Filter::kNearest, 0xffffffff, {0,0,100,200}, {200,0,300,200}, GrAA::kNo, SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(), - nullptr); + nullptr, nullptr); } } diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 7d88bc4936..a67e19a9d9 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -764,7 +764,8 @@ void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy const SkRect& srcRect, const SkRect& dstRect, GrAA aa, SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, - sk_sp<GrColorSpaceXform> colorSpaceXform) { + sk_sp<GrColorSpaceXform> textureColorSpaceXform, + sk_sp<GrColorSpaceXform> paintColorSpaceXform) { ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED SkDEBUGCODE(this->validate();) @@ -790,7 +791,8 @@ void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy } this->addDrawOp(clip, GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect, clippedDstRect, aaType, constraint, - viewMatrix, std::move(colorSpaceXform))); + viewMatrix, std::move(textureColorSpaceXform), + std::move(paintColorSpaceXform))); } void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip, diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index 565a2b8c08..4e31a1a45d 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -148,7 +148,7 @@ public: void drawTexture(const GrClip& clip, sk_sp<GrTextureProxy>, GrSamplerState::Filter, GrColor, const SkRect& srcRect, const SkRect& dstRect, GrAA aa, SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix, - sk_sp<GrColorSpaceXform>); + sk_sp<GrColorSpaceXform> texXform, sk_sp<GrColorSpaceXform> colorXform); /** * Draw a roundrect using a paint. diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp index af397cd431..9b2641ea83 100644 --- a/src/gpu/SkGpuDevice_drawTexture.cpp +++ b/src/gpu/SkGpuDevice_drawTexture.cpp @@ -99,7 +99,6 @@ static bool can_use_draw_texture(const SkPaint& paint) { static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect* src, const SkRect* dst, GrAA aa, SkCanvas::SrcRectConstraint constraint, sk_sp<GrTextureProxy> proxy, - SkColorSpace* colorSpace, const GrClip& clip, GrRenderTargetContext* rtc) { SkASSERT(!(SkToBool(src) && !SkToBool(dst))); SkRect srcRect = src ? *src : SkRect::MakeWH(proxy->width(), proxy->height()); @@ -111,7 +110,7 @@ static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect SkAssertResult(srcRect.intersect(SkRect::MakeIWH(proxy->width(), proxy->height()))); srcToDst.mapRect(&dstRect, srcRect); } - auto csxf = GrColorSpaceXform::Make(colorSpace, rtc->colorSpaceInfo().colorSpace()); + auto textureXform = GrColorSpaceXform::Make(colorSpace, rtc->colorSpaceInfo().colorSpace()); GrSamplerState::Filter filter; switch (paint.getFilterQuality()) { case kNone_SkFilterQuality: @@ -124,11 +123,18 @@ static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect case kHigh_SkFilterQuality: SK_ABORT("Quality level not allowed."); } - GrColor color = GrPixelConfigIsAlphaOnly(proxy->config()) - ? SkColorToPremulGrColor(paint.getColor()) - : SkColorAlphaToGrColor(paint.getColor()); + GrColor color; + sk_sp<GrColorSpaceXform> paintColorXform = nullptr; + if (GrPixelConfigIsAlphaOnly(proxy->config())) { + // Leave the color unpremul if we're going to transform it in the vertex shader + paintColorXform = rtc->colorSpaceInfo().refColorSpaceXformFromSRGB(); + color = paintColorXform ? SkColorToUnpremulGrColor(paint.getColor()) + : SkColorToPremulGrColor(paint.getColor()); + } else { + color = SkColorAlphaToGrColor(paint.getColor()); + } rtc->drawTexture(clip, std::move(proxy), filter, color, srcRect, dstRect, aa, constraint, ctm, - std::move(csxf)); + std::move(textureXform), std::move(paintColorXform)); } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp index 99ecdf8101..516cee628f 100644 --- a/src/gpu/ops/GrTextureOp.cpp +++ b/src/gpu/ops/GrTextureOp.cpp @@ -105,7 +105,9 @@ public: } static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt, - sk_sp<GrColorSpaceXform> csxf, bool coverageAA, + sk_sp<GrColorSpaceXform> textureColorSpaceXform, + sk_sp<GrColorSpaceXform> paintColorSpaceXform, + bool coverageAA, bool perspective, Domain domain, const GrSamplerState::Filter filters[], const GrShaderCaps& caps) { @@ -115,7 +117,9 @@ public: size_t size = sizeof(TextureGeometryProcessor) + sizeof(TextureSampler) * (samplerCnt - 1); void* mem = GrGeometryProcessor::operator new(size); return sk_sp<TextureGeometryProcessor>( - new (mem) TextureGeometryProcessor(proxies, proxyCnt, samplerCnt, std::move(csxf), + new (mem) TextureGeometryProcessor(proxies, proxyCnt, samplerCnt, + std::move(textureColorSpaceXform), + std::move(paintColorSpaceXform), coverageAA, perspective, domain, filters, caps)); } @@ -129,7 +133,8 @@ public: const char* name() const override { return "TextureGeometryProcessor"; } void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { - b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get())); + b->add32(GrColorSpaceXform::XformKey(fTextureColorSpaceXform.get())); + b->add32(GrColorSpaceXform::XformKey(fPaintColorSpaceXform.get())); uint32_t x = this->usesCoverageEdgeAA() ? 0 : 1; x |= kFloat3_GrVertexAttribType == fPositions.type() ? 0 : 2; x |= fDomain.isInitialized() ? 4 : 0; @@ -143,15 +148,20 @@ public: FPCoordTransformIter&& transformIter) override { const auto& textureGP = proc.cast<TextureGeometryProcessor>(); this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); - fColorSpaceXformHelper.setData(pdman, textureGP.fColorSpaceXform.get()); + fTextureColorSpaceXformHelper.setData( + pdman, textureGP.fTextureColorSpaceXform.get()); + fPaintColorSpaceXformHelper.setData(pdman, textureGP.fPaintColorSpaceXform.get()); } private: void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { using Interpolation = GrGLSLVaryingHandler::Interpolation; const auto& textureGP = args.fGP.cast<TextureGeometryProcessor>(); - fColorSpaceXformHelper.emitCode( - args.fUniformHandler, textureGP.fColorSpaceXform.get()); + fTextureColorSpaceXformHelper.emitCode( + args.fUniformHandler, textureGP.fTextureColorSpaceXform.get()); + fPaintColorSpaceXformHelper.emitCode( + args.fUniformHandler, textureGP.fPaintColorSpaceXform.get(), + kVertex_GrShaderFlag); if (kFloat2_GrVertexAttribType == textureGP.fPositions.type()) { args.fVaryingHandler->setNoPerspective(); } @@ -163,8 +173,20 @@ public: args.fUniformHandler, textureGP.fTextureCoords.asShaderVar(), args.fFPCoordTransformHandler); - args.fVaryingHandler->addPassThroughAttribute( - textureGP.fColors, args.fOutputColor, Interpolation::kCanBeFlat); + if (fPaintColorSpaceXformHelper.isNoop()) { + args.fVaryingHandler->addPassThroughAttribute( + textureGP.fColors, args.fOutputColor, Interpolation::kCanBeFlat); + } else { + GrGLSLVarying varying(kHalf4_GrSLType); + args.fVaryingHandler->addVarying("color", &varying); + args.fVertBuilder->codeAppend("half4 color = "); + args.fVertBuilder->appendColorGamutXform(textureGP.fColors.name(), + &fPaintColorSpaceXformHelper); + args.fVertBuilder->codeAppend(";"); + args.fVertBuilder->codeAppendf("%s = half4(color.rgb * color.a, color.a);", + varying.vsOut()); + args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn()); + } args.fFragBuilder->codeAppend("float2 texCoord;"); args.fVaryingHandler->addPassThroughAttribute(textureGP.fTextureCoords, "texCoord"); if (textureGP.fDomain.isInitialized()) { @@ -185,21 +207,17 @@ public: args.fFragBuilder->codeAppend("switch (texIdx) {"); for (int i = 0; i < textureGP.numTextureSamplers(); ++i) { args.fFragBuilder->codeAppendf("case %d: %s = ", i, args.fOutputColor); - args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor, - args.fTexSamplers[i], - "texCoord", - kFloat2_GrSLType, - &fColorSpaceXformHelper); + args.fFragBuilder->appendTextureLookupAndModulate( + args.fOutputColor, args.fTexSamplers[i], "texCoord", + kFloat2_GrSLType, &fTextureColorSpaceXformHelper); args.fFragBuilder->codeAppend("; break;"); } args.fFragBuilder->codeAppend("}"); } else { args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor); - args.fFragBuilder->appendTextureLookupAndModulate(args.fOutputColor, - args.fTexSamplers[0], - "texCoord", - kFloat2_GrSLType, - &fColorSpaceXformHelper); + args.fFragBuilder->appendTextureLookupAndModulate( + args.fOutputColor, args.fTexSamplers[0], "texCoord", + kFloat2_GrSLType, &fTextureColorSpaceXformHelper); } args.fFragBuilder->codeAppend(";"); if (textureGP.usesCoverageEdgeAA()) { @@ -244,7 +262,8 @@ public: args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage); } } - GrGLSLColorSpaceXformHelper fColorSpaceXformHelper; + GrGLSLColorSpaceXformHelper fTextureColorSpaceXformHelper; + GrGLSLColorSpaceXformHelper fPaintColorSpaceXformHelper; }; return new GLSLProcessor; } @@ -268,10 +287,13 @@ private: } TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt, - sk_sp<GrColorSpaceXform> csxf, bool coverageAA, bool perspective, - Domain domain, const GrSamplerState::Filter filters[], - const GrShaderCaps& caps) - : INHERITED(kTextureGeometryProcessor_ClassID), fColorSpaceXform(std::move(csxf)) { + sk_sp<GrColorSpaceXform> textureColorSpaceXform, + sk_sp<GrColorSpaceXform> paintColorSpaceXform, + bool coverageAA, bool perspective, Domain domain, + const GrSamplerState::Filter filters[], const GrShaderCaps& caps) + : INHERITED(kTextureGeometryProcessor_ClassID) + , fTextureColorSpaceXform(std::move(textureColorSpaceXform)) + , fPaintColorSpaceXform(std::move(paintColorSpaceXform)) { SkASSERT(proxyCnt > 0 && samplerCnt >= proxyCnt); fSamplers[0].reset(std::move(proxies[0]), filters[0]); this->addTextureSampler(&fSamplers[0]); @@ -328,7 +350,8 @@ private: Attribute fTextureIdx; Attribute fDomain; Attribute fAAEdges[4]; - sk_sp<GrColorSpaceXform> fColorSpaceXform; + sk_sp<GrColorSpaceXform> fTextureColorSpaceXform; + sk_sp<GrColorSpaceXform> fPaintColorSpaceXform; TextureSampler fSamplers[1]; typedef GrGeometryProcessor INHERITED; @@ -597,12 +620,14 @@ public: GrAAType aaType, SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, - sk_sp<GrColorSpaceXform> csxf) { + sk_sp<GrColorSpaceXform> textureColorSpaceXform, + sk_sp<GrColorSpaceXform> paintColorSpaceXform) { GrOpMemoryPool* pool = context->contextPriv().opMemoryPool(); return pool->allocate<TextureOp>(std::move(proxy), filter, color, srcRect, dstRect, aaType, constraint, - viewMatrix, std::move(csxf)); + viewMatrix, std::move(textureColorSpaceXform), + std::move(paintColorSpaceXform)); } ~TextureOp() override { @@ -685,9 +710,11 @@ __attribute__((no_sanitize("float-cast-overflow"))) TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color, const SkRect& srcRect, const SkRect& dstRect, GrAAType aaType, SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, - sk_sp<GrColorSpaceXform> csxf) + sk_sp<GrColorSpaceXform> textureColorSpaceXform, + sk_sp<GrColorSpaceXform> paintColorSpaceXform) : INHERITED(ClassID()) - , fColorSpaceXform(std::move(csxf)) + , fTextureColorSpaceXform(std::move(textureColorSpaceXform)) + , fPaintColorSpaceXform(std::move(paintColorSpaceXform)) , fProxy0(proxy.release()) , fFilter0(filter) , fProxyCnt(1) @@ -750,7 +777,8 @@ __attribute__((no_sanitize("float-cast-overflow"))) Domain domain = fDomain ? Domain::kYes : Domain::kNo; bool coverageAA = GrAAType::kCoverage == this->aaType(); sk_sp<GrGeometryProcessor> gp = TextureGeometryProcessor::Make( - proxiesSPs, fProxyCnt, std::move(fColorSpaceXform), coverageAA, fPerspective, + proxiesSPs, fProxyCnt, std::move(fTextureColorSpaceXform), + std::move(fPaintColorSpaceXform), coverageAA, fPerspective, domain, filters, *target->caps().shaderCaps()); GrPipeline::InitArgs args; args.fProxy = target->proxy(); @@ -842,7 +870,12 @@ __attribute__((no_sanitize("float-cast-overflow"))) bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { const auto* that = t->cast<TextureOp>(); const auto& shaderCaps = *caps.shaderCaps(); - if (!GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) { + if (!GrColorSpaceXform::Equals(fTextureColorSpaceXform.get(), + that->fTextureColorSpaceXform.get())) { + return false; + } + if (!GrColorSpaceXform::Equals(fPaintColorSpaceXform.get(), + that->fPaintColorSpaceXform.get())) { return false; } if (this->aaType() != that->aaType()) { @@ -850,7 +883,8 @@ __attribute__((no_sanitize("float-cast-overflow"))) } // Because of an issue where GrColorSpaceXform adds the same function every time it is used // in a texture lookup, we only allow multiple textures when there is no transform. - if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) && !fColorSpaceXform && + if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) && + !fTextureColorSpaceXform && fMaxApproxDstPixelArea <= shaderCaps.disableImageMultitexturingDstRectAreaThreshold() && that->fMaxApproxDstPixelArea <= shaderCaps.disableImageMultitexturingDstRectAreaThreshold()) { @@ -999,7 +1033,8 @@ __attribute__((no_sanitize("float-cast-overflow"))) GrColor fColor; }; SkSTArray<1, Draw, true> fDraws; - sk_sp<GrColorSpaceXform> fColorSpaceXform; + sk_sp<GrColorSpaceXform> fTextureColorSpaceXform; + sk_sp<GrColorSpaceXform> fPaintColorSpaceXform; // Initially we store a single proxy ptr and a single filter. If we grow to have more than // one proxy we instead store pointers to dynamically allocated arrays of size kMaxTextures // followed by kMaxTextures filters. @@ -1035,9 +1070,11 @@ std::unique_ptr<GrDrawOp> Make(GrContext* context, GrAAType aaType, SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, - sk_sp<GrColorSpaceXform> csxf) { + sk_sp<GrColorSpaceXform> textureColorSpaceXform, + sk_sp<GrColorSpaceXform> paintColorSpaceXform) { return TextureOp::Make(context, std::move(proxy), filter, color, srcRect, dstRect, aaType, - constraint, viewMatrix, std::move(csxf)); + constraint, viewMatrix, std::move(textureColorSpaceXform), + std::move(paintColorSpaceXform)); } } // namespace GrTextureOp @@ -1078,7 +1115,8 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) { filter = (GrSamplerState::Filter)random->nextULessThan( static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1); } - auto csxf = GrTest::TestColorXform(random); + auto texXform = GrTest::TestColorXform(random); + auto paintXform = GrTest::TestColorXform(random); GrAAType aaType = GrAAType::kNone; if (random->nextBool()) { aaType = (fsaaType == GrFSAAType::kUnifiedMSAA) ? GrAAType::kMSAA : GrAAType::kCoverage; @@ -1086,7 +1124,7 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) { auto constraint = random->nextBool() ? SkCanvas::kStrict_SrcRectConstraint : SkCanvas::kFast_SrcRectConstraint; return GrTextureOp::Make(context, std::move(proxy), filter, color, srcRect, rect, aaType, - constraint, viewMatrix, std::move(csxf)); + constraint, viewMatrix, std::move(texXform), std::move(paintXform)); } #endif diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h index 7211b5edc2..96cbc70cb8 100644 --- a/src/gpu/ops/GrTextureOp.h +++ b/src/gpu/ops/GrTextureOp.h @@ -34,5 +34,6 @@ std::unique_ptr<GrDrawOp> Make(GrContext*, GrAAType, SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix, - sk_sp<GrColorSpaceXform>); + sk_sp<GrColorSpaceXform> textureXform, + sk_sp<GrColorSpaceXform> paintXform); } |