diff options
author | Leon Scroggins III <scroggo@google.com> | 2018-05-08 12:07:23 -0400 |
---|---|---|
committer | Leon Scroggins <scroggo@google.com> | 2018-05-08 16:52:08 +0000 |
commit | 38784599f39026f54aa56b3c6e34afc15e00abd6 (patch) | |
tree | b8db60517295629cfdc00f98f9fc4fd9d85f0655 | |
parent | a172bd75619900fc0abda81670e772f07ba4a1d9 (diff) | |
download | skia-38784599f39026f54aa56b3c6e34afc15e00abd6.tar.gz |
Cherry-pick of "Make GPU lattice/nine patch not bleed across cells."
Consolidate code for handling various image/bitmap and lattice/ninepatch flavors.
Makes refTextureForParams virtual on GrTextureProducer. Previously both subclasses had non-virtual flavors of this.
Bug: b/77917978
Reviewed-on: https://skia-review.googlesource.com/125520
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
No-Tree-Checks: true
No-Try: true
No-Presubmit: true
Conflicts:
src/gpu/GrTextureAdjuster.cpp:
- https://skia-review.googlesource.com/114985 switched from
gpu->isACopyNeededForTextureParams to a static version. Continue
using the old version, as the static version does not yet exist.
Restore check for !gpu
- https://skia-review.googlesource.com/121104 added an assert. Comment
it out.
src/gpu/GrTextureMaker.cpp:
- https://skia-review.googlesource.com/121104 added a check for max
texture size. Comment it out.
src/gpu/ops/GrLatticeOp.cpp:
- Did not come up in the cherry-pick, but a logical conflict appeared
when building DM. https://skia-review.googlesource.com/111806 moved
GrSurfaceOrigin from GrSurfaceDesc to the proxy. In this branch, we
need to set it on GrSurfaceDesc.
Change-Id: I9dcb9ebf7432549ac35000b683094e3dc0fa1ede
Reviewed-on: https://skia-review.googlesource.com/126824
Reviewed-by: Leon Scroggins <scroggo@google.com>
-rw-r--r-- | src/gpu/GrGpu.cpp | 1 | ||||
-rw-r--r-- | src/gpu/GrProcessor.h | 1 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 10 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.h | 9 | ||||
-rw-r--r-- | src/gpu/GrTextureAdjuster.cpp | 17 | ||||
-rw-r--r-- | src/gpu/GrTextureAdjuster.h | 14 | ||||
-rw-r--r-- | src/gpu/GrTextureMaker.cpp | 8 | ||||
-rw-r--r-- | src/gpu/GrTextureMaker.h | 17 | ||||
-rw-r--r-- | src/gpu/GrTextureProducer.cpp | 22 | ||||
-rw-r--r-- | src/gpu/GrTextureProducer.h | 34 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 116 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 11 | ||||
-rw-r--r-- | src/gpu/ops/GrLatticeOp.cpp | 244 | ||||
-rw-r--r-- | src/gpu/ops/GrLatticeOp.h | 11 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 6 | ||||
-rw-r--r-- | src/image/SkImage_Raster.cpp | 6 |
16 files changed, 343 insertions, 184 deletions
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index a53dc8a98a..ec246ae1da 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -54,6 +54,7 @@ bool GrGpu::isACopyNeededForTextureParams(int width, int height, SkASSERT(scaleAdjust); copyParams->fWidth = GrNextPow2(width); copyParams->fHeight = GrNextPow2(height); + SkASSERT(scaleAdjust); scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width; scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height; switch (textureParams.filter()) { diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h index 64a28d83e9..c7704dbdf1 100644 --- a/src/gpu/GrProcessor.h +++ b/src/gpu/GrProcessor.h @@ -140,6 +140,7 @@ public: kGrYUVtoRGBEffect_ClassID, kHighContrastFilterEffect_ClassID, kInstanceProcessor_ClassID, + kLatticeGP_ClassID, kLumaColorFilterEffect_ClassID, kMSAAQuadProcessor_ClassID, kPDLCDXferProcessor_ClassID, diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index a95f25198b..2d760e12af 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1361,8 +1361,9 @@ void GrRenderTargetContext::drawArc(const GrClip& clip, void GrRenderTargetContext::drawImageLattice(const GrClip& clip, GrPaint&& paint, const SkMatrix& viewMatrix, - int imageWidth, - int imageHeight, + sk_sp<GrTextureProxy> image, + sk_sp<GrColorSpaceXform> csxf, + GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) { ASSERT_SINGLE_OWNER @@ -1372,8 +1373,9 @@ void GrRenderTargetContext::drawImageLattice(const GrClip& clip, AutoCheckFlush acf(this->drawingManager()); - std::unique_ptr<GrDrawOp> op = GrLatticeOp::MakeNonAA(std::move(paint), viewMatrix, imageWidth, - imageHeight, std::move(iter), dst); + std::unique_ptr<GrDrawOp> op = + GrLatticeOp::MakeNonAA(std::move(paint), viewMatrix, std::move(image), std::move(csxf), + filter, std::move(iter), dst); this->addDrawOp(clip, std::move(op)); } diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index 6525866ee0..04ae319578 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -309,11 +309,12 @@ public: * Draw the image as a set of rects, specified by |iter|. */ void drawImageLattice(const GrClip&, - GrPaint&& paint, + GrPaint&&, const SkMatrix& viewMatrix, - int imageWidth, - int imageHeight, - std::unique_ptr<SkLatticeIter> iter, + sk_sp<GrTextureProxy>, + sk_sp<GrColorSpaceXform>, + GrSamplerState::Filter, + std::unique_ptr<SkLatticeIter>, const SkRect& dst); /** diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp index fbfffb3bb8..2426a1857c 100644 --- a/src/gpu/GrTextureAdjuster.cpp +++ b/src/gpu/GrTextureAdjuster.cpp @@ -65,8 +65,11 @@ sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& c return copy; } -sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(const GrSamplerState& params, - SkScalar scaleAdjust[2]) { +sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams( + const GrSamplerState& params, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* texColorSpace, + SkScalar scaleAdjust[2]) { sk_sp<GrTextureProxy> proxy = this->originalProxyRef(); CopyParams copyParams; @@ -75,7 +78,15 @@ sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(const GrSa return nullptr; } + if (texColorSpace) { + *texColorSpace = sk_ref_sp(fColorSpace); + } + GrGpu* gpu = fContext->contextPriv().getGpu(); + if (!gpu) { + return proxy; + } + if (!gpu->isACopyNeededForTextureParams(proxy.get(), params, ©Params, scaleAdjust)) { return proxy; } @@ -100,7 +111,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor( } SkScalar scaleAdjust[2] = { 1.0f, 1.0f }; sk_sp<GrTextureProxy> proxy( - this->refTextureProxySafeForParams(samplerState, scaleAdjust)); + this->refTextureProxyForParams(samplerState, nullptr, nullptr, scaleAdjust)); if (!proxy) { return nullptr; } diff --git a/src/gpu/GrTextureAdjuster.h b/src/gpu/GrTextureAdjuster.h index a0ce8c40db..885e39059d 100644 --- a/src/gpu/GrTextureAdjuster.h +++ b/src/gpu/GrTextureAdjuster.h @@ -20,11 +20,6 @@ */ class GrTextureAdjuster : public GrTextureProducer { public: - /** Makes the subset of the texture safe to use with the given texture parameters. If the copy's - size does not match subset's dimensions then the contents are scaled to fit the copy.*/ - sk_sp<GrTextureProxy> refTextureProxySafeForParams(const GrSamplerState&, - SkScalar scaleAdjust[2]); - std::unique_ptr<GrFragmentProcessor> createFragmentProcessor( const SkMatrix& textureMatrix, const SkRect& constraintRect, @@ -48,14 +43,19 @@ protected: sk_sp<GrTextureProxy> originalProxyRef() const { return fOriginal; } private: + sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* proxyColorSpace, + SkScalar scaleAdjust[2]) override; + + sk_sp<GrTextureProxy> refTextureProxyCopy(const CopyParams& copyParams, bool willBeMipped); + GrContext* fContext; sk_sp<GrTextureProxy> fOriginal; SkAlphaType fAlphaType; SkColorSpace* fColorSpace; uint32_t fUniqueID; - sk_sp<GrTextureProxy> refTextureProxyCopy(const CopyParams ©Params, bool willBeMipped); - typedef GrTextureProducer INHERITED; }; diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp index 5043675a0d..7d7431bbf2 100644 --- a/src/gpu/GrTextureMaker.cpp +++ b/src/gpu/GrTextureMaker.cpp @@ -13,10 +13,10 @@ #include "GrGpu.h" #include "GrProxyProvider.h" -sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerState& params, - SkColorSpace* dstColorSpace, - sk_sp<SkColorSpace>* texColorSpace, - SkScalar scaleAdjust[2]) { +sk_sp<GrTextureProxy> GrTextureMaker::onRefTextureProxyForParams(const GrSamplerState& params, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* texColorSpace, + SkScalar scaleAdjust[2]) { CopyParams copyParams; bool willBeMipped = params.filter() == GrSamplerState::Filter::kMipMap; diff --git a/src/gpu/GrTextureMaker.h b/src/gpu/GrTextureMaker.h index b482170d49..6c8cd0407e 100644 --- a/src/gpu/GrTextureMaker.h +++ b/src/gpu/GrTextureMaker.h @@ -18,18 +18,6 @@ class GrTextureMaker : public GrTextureProducer { public: enum class AllowedTexGenType : bool { kCheap, kAny }; - /** - * Returns a texture that is safe for use with the params. If the size of the returned texture - * does not match width()/height() then the contents of the original must be scaled to fit - * the texture. Additionally, the 'scaleAdjust' must be applied to the texture matrix - * in order to correct the absolute texture coordinates. - * Places the color space of the texture in (*texColorSpace). - */ - sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&, - SkColorSpace* dstColorSpace, - sk_sp<SkColorSpace>* texColorSpace, - SkScalar scaleAdjust[2]); - std::unique_ptr<GrFragmentProcessor> createFragmentProcessor( const SkMatrix& textureMatrix, const SkRect& constraintRect, @@ -77,6 +65,11 @@ protected: GrContext* context() const { return fContext; } private: + sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* proxyColorSpace, + SkScalar scaleAdjust[2]) override; + GrContext* fContext; typedef GrTextureProducer INHERITED; diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp index f1c8c8dbd0..46a80944e6 100644 --- a/src/gpu/GrTextureProducer.cpp +++ b/src/gpu/GrTextureProducer.cpp @@ -207,3 +207,25 @@ std::unique_ptr<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorF } } } + +sk_sp<GrTextureProxy> GrTextureProducer::refTextureProxyForParams( + const GrSamplerState& sampler, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* proxyColorSpace, + SkScalar scaleAdjust[2]) { + // Check that the caller pre-initialized scaleAdjust + SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1)); + // Check that if the caller passed nullptr for scaleAdjust that we're in the case where there + // can be no scaling. + SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap && + !sampler.isRepeated())); + SkASSERT(scaleAdjust || expectNoScale); + auto result = + this->onRefTextureProxyForParams(sampler, dstColorSpace, proxyColorSpace, scaleAdjust); + + // Check that the "no scaling expected" case always returns a proxy of the same size as the + // producer. + SkASSERT(!result || !expectNoScale || + (result->width() == this->width() && result->height() == this->height())); + return result; +} diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h index 88ba14afa8..467948dfa6 100644 --- a/src/gpu/GrTextureProducer.h +++ b/src/gpu/GrTextureProducer.h @@ -69,6 +69,35 @@ public: const GrSamplerState::Filter* filterOrNullForBicubic, SkColorSpace* dstColorSpace) = 0; + /** + * Returns a texture that is safe for use with the params. + * + * If the size of the returned texture does not match width()/height() then the contents of the + * original may have been scaled to fit the texture or the original may have been copied into + * a subrect of the copy. 'scaleAdjust' must be applied to the normalized texture coordinates + * in order to correct for the latter case. + * + * If the GrSamplerState is known to clamp and use kNearest or kBilerp filter mode then the + * proxy will always be unscaled and nullptr can be passed for scaleAdjust. There is a weird + * contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling + * this method. (TODO: Fix this and make this function always initialize scaleAdjust). + * + * Places the color space of the texture in (*proxyColorSpace). + */ + sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* proxyColorSpace, + SkScalar scaleAdjust[2]); + + sk_sp<GrTextureProxy> refTextureProxyForParams(GrSamplerState::Filter filter, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* proxyColorSpace, + SkScalar scaleAdjust[2]) { + return this->refTextureProxyForParams( + GrSamplerState(GrSamplerState::WrapMode::kClamp, filter), dstColorSpace, + proxyColorSpace, scaleAdjust); + } + virtual ~GrTextureProducer() {} int width() const { return fWidth; } @@ -142,6 +171,11 @@ protected: const GrSamplerState::Filter* filterOrNullForBicubic); private: + virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&, + SkColorSpace* dstColorSpace, + sk_sp<SkColorSpace>* proxyColorSpace, + SkScalar scaleAdjust[2]) = 0; + const int fWidth; const int fHeight; const bool fIsAlphaOnly; diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index c6bb780d1d..9b5a5a9338 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -6,6 +6,7 @@ */ #include "SkGpuDevice.h" +#include "../private/SkShadowFlags.h" #include "GrBitmapTextureMaker.h" #include "GrBlurUtils.h" #include "GrColorSpaceXform.h" @@ -28,6 +29,7 @@ #include "SkImageInfoPriv.h" #include "SkImage_Base.h" #include "SkLatticeIter.h" +#include "SkMakeUnique.h" #include "SkMaskFilterBase.h" #include "SkPathEffect.h" #include "SkPicture.h" @@ -48,7 +50,6 @@ #include "effects/GrBicubicEffect.h" #include "effects/GrSimpleTextureEffect.h" #include "effects/GrTextureDomain.h" -#include "../private/SkShadowFlags.h" #include "text/GrTextUtils.h" #if SK_SUPPORT_GPU @@ -976,15 +977,16 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap, bitmap.height() <= fContext->caps()->maxTileSize()); SkASSERT(!samplerState.isRepeated()); + SkScalar scales[2] = {1.f, 1.f}; sk_sp<GrTextureProxy> proxy = - GrRefCachedBitmapTextureProxy(fContext.get(), bitmap, samplerState, nullptr); + GrRefCachedBitmapTextureProxy(fContext.get(), bitmap, samplerState, scales); if (!proxy) { return; } // Compute a matrix that maps the rect we will draw to the src rect. - const SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, - SkMatrix::kFill_ScaleToFit); + SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit); + texMatrix.postScale(scales[0], scales[1]); // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring // the rest from the SkPaint. @@ -1361,66 +1363,25 @@ static GrSamplerState::Filter compute_lattice_filter_mode(const SkPaint& paint) return GrSamplerState::Filter::kBilerp; } -void SkGpuDevice::drawProducerNine(GrTextureProducer* producer, - const SkIRect& center, const SkRect& dst, const SkPaint& paint) { - GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerNine", fContext.get()); - - bool useFallback = paint.getMaskFilter() || paint.isAntiAlias() || - GrFSAAType::kUnifiedMSAA == fRenderTargetContext->fsaaType(); - bool doBicubic; - GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode( - paint.getFilterQuality(), this->ctm(), SkMatrix::I(), - fContext->contextPriv().sharpenMipmappedTextures(), &doBicubic); - if (useFallback || doBicubic || GrSamplerState::Filter::kNearest != textureFilterMode) { - SkLatticeIter iter(producer->width(), producer->height(), center, dst); - - SkRect srcR, dstR; - while (iter.next(&srcR, &dstR)) { - this->drawTextureProducer(producer, &srcR, &dstR, SkCanvas::kStrict_SrcRectConstraint, - this->ctm(), paint); - } - return; - } - - const GrSamplerState::Filter kMode = compute_lattice_filter_mode(paint); - auto fp = producer->createFragmentProcessor( - SkMatrix::I(), SkRect::MakeIWH(producer->width(), producer->height()), - GrTextureProducer::kNo_FilterConstraint, true, &kMode, - fRenderTargetContext->colorSpaceInfo().colorSpace()); - if (!fp) { - return; - } - GrPaint grPaint; - if (!SkPaintToGrPaintWithTexture(this->context(), fRenderTargetContext->colorSpaceInfo(), paint, - this->ctm(), std::move(fp), producer->isAlphaOnly(), - &grPaint)) { - return; - } - - std::unique_ptr<SkLatticeIter> iter( - new SkLatticeIter(producer->width(), producer->height(), center, dst)); - fRenderTargetContext->drawImageLattice(this->clip(), std::move(grPaint), this->ctm(), - producer->width(), producer->height(), std::move(iter), - dst); -} - void SkGpuDevice::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, const SkPaint& paint) { ASSERT_SINGLE_OWNER uint32_t pinnedUniqueID; + auto iter = skstd::make_unique<SkLatticeIter>(image->width(), image->height(), center, dst); if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(&pinnedUniqueID)) { GrTextureAdjuster adjuster(this->context(), std::move(proxy), image->alphaType(), pinnedUniqueID, as_IB(image)->onImageInfo().colorSpace()); - this->drawProducerNine(&adjuster, center, dst, paint); + this->drawProducerLattice(&adjuster, std::move(iter), dst, paint); } else { SkBitmap bm; if (image->isLazyGenerated()) { GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint); - this->drawProducerNine(&maker, center, dst, paint); + this->drawProducerLattice(&maker, std::move(iter), dst, paint); } else if (as_IB(image)->getROPixels(&bm, fRenderTargetContext->colorSpaceInfo().colorSpace())) { - this->drawBitmapNine(bm, center, dst, paint); + GrBitmapTextureMaker maker(fContext.get(), bm); + this->drawProducerLattice(&maker, std::move(iter), dst, paint); } } } @@ -1428,35 +1389,47 @@ void SkGpuDevice::drawImageNine(const SkImage* image, void SkGpuDevice::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint& paint) { ASSERT_SINGLE_OWNER + auto iter = skstd::make_unique<SkLatticeIter>(bitmap.width(), bitmap.height(), center, dst); GrBitmapTextureMaker maker(fContext.get(), bitmap); - this->drawProducerNine(&maker, center, dst, paint); + this->drawProducerLattice(&maker, std::move(iter), dst, paint); } void SkGpuDevice::drawProducerLattice(GrTextureProducer* producer, - const SkCanvas::Lattice& lattice, const SkRect& dst, - const SkPaint& paint) { + std::unique_ptr<SkLatticeIter> iter, const SkRect& dst, + const SkPaint& origPaint) { GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerLattice", fContext.get()); + SkTCopyOnFirstWrite<SkPaint> paint(&origPaint); - const GrSamplerState::Filter kMode = compute_lattice_filter_mode(paint); - std::unique_ptr<GrFragmentProcessor> fp(producer->createFragmentProcessor( - SkMatrix::I(), SkRect::MakeIWH(producer->width(), producer->height()), - GrTextureProducer::kNo_FilterConstraint, true, &kMode, - fRenderTargetContext->colorSpaceInfo().colorSpace())); - if (!fp) { + bool useFallback = paint->getMaskFilter() || paint->isAntiAlias() || + GrFSAAType::kUnifiedMSAA == fRenderTargetContext->fsaaType(); + if (useFallback) { + SkRect srcR, dstR; + while (iter->next(&srcR, &dstR)) { + this->drawTextureProducer(producer, &srcR, &dstR, SkCanvas::kStrict_SrcRectConstraint, + this->ctm(), *paint); + } return; } + + if (!producer->isAlphaOnly() && (paint->getColor() & 0x00FFFFFF) != 0x00FFFFFF) { + paint.writable()->setColor(SkColorSetARGB(origPaint.getAlpha(), 0xFF, 0xFF, 0xFF)); + } GrPaint grPaint; - if (!SkPaintToGrPaintWithTexture(this->context(), fRenderTargetContext->colorSpaceInfo(), paint, - this->ctm(), std::move(fp), producer->isAlphaOnly(), - &grPaint)) { + if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), fRenderTargetContext->colorSpaceInfo(), + *paint, &grPaint)) { return; } - std::unique_ptr<SkLatticeIter> iter( - new SkLatticeIter(lattice, dst)); + auto dstColorSpace = fRenderTargetContext->colorSpaceInfo().colorSpace(); + const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint); + sk_sp<SkColorSpace> proxyColorSpace; + auto proxy = + producer->refTextureProxyForParams(filter, dstColorSpace, &proxyColorSpace, nullptr); + auto csxf = GrColorSpaceXform::Make(proxyColorSpace.get(), proxy->config(), dstColorSpace); + fRenderTargetContext->drawImageLattice(this->clip(), std::move(grPaint), this->ctm(), - producer->width(), producer->height(), std::move(iter), - dst); + std::move(proxy), std::move(csxf), filter, + std::move(iter), dst); } void SkGpuDevice::drawImageLattice(const SkImage* image, @@ -1464,19 +1437,21 @@ void SkGpuDevice::drawImageLattice(const SkImage* image, const SkPaint& paint) { ASSERT_SINGLE_OWNER uint32_t pinnedUniqueID; + auto iter = skstd::make_unique<SkLatticeIter>(lattice, dst); if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(&pinnedUniqueID)) { GrTextureAdjuster adjuster(this->context(), std::move(proxy), image->alphaType(), pinnedUniqueID, as_IB(image)->onImageInfo().colorSpace()); - this->drawProducerLattice(&adjuster, lattice, dst, paint); + this->drawProducerLattice(&adjuster, std::move(iter), dst, paint); } else { SkBitmap bm; if (image->isLazyGenerated()) { GrImageTextureMaker maker(fContext.get(), image, SkImage::kAllow_CachingHint); - this->drawProducerLattice(&maker, lattice, dst, paint); + this->drawProducerLattice(&maker, std::move(iter), dst, paint); } else if (as_IB(image)->getROPixels(&bm, fRenderTargetContext->colorSpaceInfo().colorSpace())) { - this->drawBitmapLattice(bm, lattice, dst, paint); + GrBitmapTextureMaker maker(fContext.get(), bm); + this->drawProducerLattice(&maker, std::move(iter), dst, paint); } } } @@ -1485,8 +1460,9 @@ void SkGpuDevice::drawBitmapLattice(const SkBitmap& bitmap, const SkCanvas::Lattice& lattice, const SkRect& dst, const SkPaint& paint) { ASSERT_SINGLE_OWNER + auto iter = skstd::make_unique<SkLatticeIter>(lattice, dst); GrBitmapTextureMaker maker(fContext.get(), bitmap); - this->drawProducerLattice(&maker, lattice, dst, paint); + this->drawProducerLattice(&maker, std::move(iter), dst, paint); } static bool init_vertices_paint(GrContext* context, const GrColorSpaceInfo& colorSpaceInfo, diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index da691a3da3..6a3f22d6e7 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -241,16 +241,9 @@ private: const SkMatrix& srcToDstMatrix, const SkPaint&); - bool drawFilledDRRect(const SkMatrix& viewMatrix, const SkRRect& outer, - const SkRRect& inner, const SkPaint& paint); - - void drawProducerNine(GrTextureProducer*, const SkIRect& center, - const SkRect& dst, const SkPaint&); - - void drawProducerLattice(GrTextureProducer*, const SkCanvas::Lattice& lattice, - const SkRect& dst, const SkPaint&); + void drawProducerLattice(GrTextureProducer*, std::unique_ptr<SkLatticeIter>, const SkRect& dst, + const SkPaint&); - bool drawDashLine(const SkPoint pts[2], const SkPaint& paint); void drawStrokedLine(const SkPoint pts[2], const SkPaint&); void wireframeVertices(SkVertices::VertexMode, int vertexCount, const SkPoint verts[], diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp index 45081a02fd..79cbf9dd41 100644 --- a/src/gpu/ops/GrLatticeOp.cpp +++ b/src/gpu/ops/GrLatticeOp.cpp @@ -17,15 +17,104 @@ #include "SkMatrixPriv.h" #include "SkPointPriv.h" #include "SkRect.h" - -static sk_sp<GrGeometryProcessor> create_gp() { - using namespace GrDefaultGeoProcFactory; - return GrDefaultGeoProcFactory::Make(Color::kPremulGrColorAttribute_Type, Coverage::kSolid_Type, - LocalCoords::kHasExplicit_Type, SkMatrix::I()); -} +#include "glsl/GrGLSLColorSpaceXformHelper.h" +#include "glsl/GrGLSLGeometryProcessor.h" +#include "glsl/GrGLSLVarying.h" namespace { +class LatticeGP : public GrGeometryProcessor { +public: + struct Vertex { + SkPoint fPosition; + SkPoint fTextureCoords; + SkRect fTextureDomain; + GrColor fColor; + }; + + static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxy, + sk_sp<GrColorSpaceXform> csxf, + GrSamplerState::Filter filter) { + return sk_sp<GrGeometryProcessor>(new LatticeGP(std::move(proxy), std::move(csxf), filter)); + } + + const char* name() const override { return "LatticeGP"; } + + void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { + b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get())); + } + + GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override { + class GLSLProcessor : public GrGLSLGeometryProcessor { + public: + void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, + FPCoordTransformIter&& transformIter) override { + const auto& latticeGP = proc.cast<LatticeGP>(); + this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); + if (fColorSpaceXformHelper.isValid()) { + fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get()); + } + } + + private: + void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { + using Interpolation = GrGLSLVaryingHandler::Interpolation; + const auto& latticeGP = args.fGP.cast<LatticeGP>(); + fColorSpaceXformHelper.emitCode(args.fUniformHandler, + latticeGP.fColorSpaceXform.get()); + + args.fVaryingHandler->emitAttributes(latticeGP); + this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fPositions.fName); + this->emitTransforms(args.fVertBuilder, + args.fVaryingHandler, + args.fUniformHandler, + latticeGP.fTextureCoords.asShaderVar(), + args.fFPCoordTransformHandler); + args.fFragBuilder->codeAppend("float2 textureCoords;"); + args.fVaryingHandler->addPassThroughAttribute(&latticeGP.fTextureCoords, + "textureCoords"); + args.fFragBuilder->codeAppend("float4 textureDomain;"); + args.fVaryingHandler->addPassThroughAttribute( + &latticeGP.fTextureDomain, "textureDomain", Interpolation::kCanBeFlat); + args.fVaryingHandler->addPassThroughAttribute(&latticeGP.fColors, args.fOutputColor, + Interpolation::kCanBeFlat); + args.fFragBuilder->codeAppendf("%s = ", args.fOutputColor); + args.fFragBuilder->appendTextureLookupAndModulate( + args.fOutputColor, + args.fTexSamplers[0], + "clamp(textureCoords, textureDomain.xy, textureDomain.zw)", + kFloat2_GrSLType, + &fColorSpaceXformHelper); + args.fFragBuilder->codeAppend(";"); + args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage); + } + GrGLSLColorSpaceXformHelper fColorSpaceXformHelper; + }; + return new GLSLProcessor; + } + +private: + LatticeGP(sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> csxf, + GrSamplerState::Filter filter) + : INHERITED(kLatticeGP_ClassID), fColorSpaceXform(std::move(csxf)) { + fPositions = this->addVertexAttrib("position", kFloat2_GrVertexAttribType); + fSampler.reset(std::move(proxy), filter); + this->addTextureSampler(&fSampler); + fTextureCoords = this->addVertexAttrib("textureCoords", kFloat2_GrVertexAttribType); + fTextureDomain = this->addVertexAttrib("textureDomain", kFloat4_GrVertexAttribType); + fColors = this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType); + } + + Attribute fPositions; + Attribute fTextureCoords; + Attribute fTextureDomain; + Attribute fColors; + sk_sp<GrColorSpaceXform> fColorSpaceXform; + TextureSampler fSampler; + + typedef GrGeometryProcessor INHERITED; +}; + class NonAALatticeOp final : public GrMeshDrawOp { private: using Helper = GrSimpleMeshDrawOpHelper; @@ -37,25 +126,30 @@ public: static const int kIndicesPerRect = 6; static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const SkMatrix& viewMatrix, - int imageWidth, int imageHeight, + sk_sp<GrTextureProxy> proxy, + sk_sp<GrColorSpaceXform> colorSpaceXForm, + GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) { - return Helper::FactoryHelper<NonAALatticeOp>(std::move(paint), viewMatrix, imageWidth, - imageHeight, std::move(iter), dst); + return Helper::FactoryHelper<NonAALatticeOp>(std::move(paint), viewMatrix, std::move(proxy), + std::move(colorSpaceXForm), filter, + std::move(iter), dst); } NonAALatticeOp(Helper::MakeArgs& helperArgs, GrColor color, const SkMatrix& viewMatrix, - int imageWidth, int imageHeight, std::unique_ptr<SkLatticeIter> iter, + sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> colorSpaceXform, + GrSamplerState::Filter filter, std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) - : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kNone) { + : INHERITED(ClassID()) + , fHelper(helperArgs, GrAAType::kNone) + , fProxy(std::move(proxy)) + , fColorSpaceXform(std::move(colorSpaceXform)) + , fFilter(filter) { Patch& patch = fPatches.push_back(); patch.fViewMatrix = viewMatrix; patch.fColor = color; patch.fIter = std::move(iter); patch.fDst = dst; - fImageWidth = imageWidth; - fImageHeight = imageHeight; - // setup bounds this->setTransformedBounds(patch.fDst, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); } @@ -84,14 +178,19 @@ public: RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip, GrPixelConfigIsClamped dstIsClamped) override { - return fHelper.xpRequiresDstTexture(caps, clip, dstIsClamped, - GrProcessorAnalysisCoverage::kNone, - &fPatches.front().fColor); + auto opaque = GrColorIsOpaque(fPatches[0].fColor) && GrPixelConfigIsOpaque(fProxy->config()) + ? GrProcessorAnalysisColor::Opaque::kYes + : GrProcessorAnalysisColor::Opaque::kNo; + auto analysisColor = GrProcessorAnalysisColor(opaque); + auto result = fHelper.xpRequiresDstTexture( + caps, clip, dstIsClamped, GrProcessorAnalysisCoverage::kNone, &analysisColor); + analysisColor.isConstant(&fPatches[0].fColor); + return result; } private: void onPrepareDraws(Target* target) override { - sk_sp<GrGeometryProcessor> gp(create_gp()); + auto gp = LatticeGP::Make(fProxy, fColorSpaceXform, fFilter); if (!gp) { SkDebugf("Couldn't create GrGeometryProcessor\n"); return; @@ -128,24 +227,35 @@ private: patch.fIter->mapDstScaleTranslate(patch.fViewMatrix); } - SkRect srcR, dstR; + SkIRect srcR; + SkRect dstR; intptr_t patchVerts = verts; + Sk4f scales(1.f / fProxy->width(), 1.f / fProxy->height(), + 1.f / fProxy->width(), 1.f / fProxy->height()); + static const Sk4f kDomainOffsets(0.5f, 0.5f, -0.5f, -0.5f); + static const Sk4f kFlipOffsets(0.f, 1, 0.f, 1.f); + static const Sk4f kFlipMuls(1.f, -1.f, 1.f, -1.f); while (patch.fIter->next(&srcR, &dstR)) { - SkPoint* positions = reinterpret_cast<SkPoint*>(verts); - SkPointPriv::SetRectTriStrip(positions, dstR.fLeft, dstR.fTop, dstR.fRight, - dstR.fBottom, vertexStride); - - // Setup local coords - static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); - SkPoint* coords = reinterpret_cast<SkPoint*>(verts + kLocalOffset); - SkPointPriv::SetRectTriStrip(coords, srcR.fLeft, srcR.fTop, srcR.fRight, - srcR.fBottom, vertexStride); - - static const int kColorOffset = sizeof(SkPoint); - GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset); - for (int j = 0; j < 4; ++j) { - *vertColor = patch.fColor; - vertColor = (GrColor*)((intptr_t)vertColor + vertexStride); + auto vertices = reinterpret_cast<LatticeGP::Vertex*>(verts); + SkPointPriv::SetRectTriStrip(&vertices->fPosition, dstR.fLeft, dstR.fTop, + dstR.fRight, dstR.fBottom, vertexStride); + Sk4f coords(SkIntToScalar(srcR.fLeft), SkIntToScalar(srcR.fTop), + SkIntToScalar(srcR.fRight), SkIntToScalar(srcR.fBottom)); + Sk4f domain = coords + kDomainOffsets; + coords *= scales; + domain *= scales; + if (fProxy->origin() == kBottomLeft_GrSurfaceOrigin) { + coords = kFlipMuls * coords + kFlipOffsets; + domain = SkNx_shuffle<0, 3, 2, 1>(kFlipMuls * domain + kFlipOffsets); + } + SkPointPriv::SetRectTriStrip(&vertices->fTextureCoords, coords[0], coords[1], + coords[2], coords[3], vertexStride); + for (int j = 0; j < kVertsPerRect; ++j) { + vertices[j].fTextureDomain = {domain[0], domain[1], domain[2], domain[3]}; + } + + for (int j = 0; j < kVertsPerRect; ++j) { + vertices[j].fColor = patch.fColor; } verts += kVertsPerRect * vertexStride; } @@ -162,13 +272,19 @@ private: bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { NonAALatticeOp* that = t->cast<NonAALatticeOp>(); + if (fProxy != that->fProxy) { + return false; + } + if (fFilter != that->fFilter) { + return false; + } + if (GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) { + return false; + } if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { return false; } - SkASSERT(this->fImageWidth == that->fImageWidth && - this->fImageHeight == that->fImageHeight); - fPatches.move_back_n(that->fPatches.count(), that->fPatches.begin()); this->joinBounds(*that); return true; @@ -183,8 +299,9 @@ private: Helper fHelper; SkSTArray<1, Patch, true> fPatches; - int fImageWidth; - int fImageHeight; + sk_sp<GrTextureProxy> fProxy; + sk_sp<GrColorSpaceXform> fColorSpaceXform; + GrSamplerState::Filter fFilter; typedef GrMeshDrawOp INHERITED; }; @@ -192,15 +309,19 @@ private: } // anonymous namespace namespace GrLatticeOp { -std::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&& paint, const SkMatrix& viewMatrix, int imageWidth, - int imageHeight, std::unique_ptr<SkLatticeIter> iter, - const SkRect& dst) { - return NonAALatticeOp::Make(std::move(paint), viewMatrix, imageWidth, imageHeight, - std::move(iter), dst); +std::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&& paint, const SkMatrix& viewMatrix, + sk_sp<GrTextureProxy> proxy, + sk_sp<GrColorSpaceXform> colorSpaceXform, + GrSamplerState::Filter filter, + std::unique_ptr<SkLatticeIter> iter, const SkRect& dst) { + return NonAALatticeOp::Make(std::move(paint), viewMatrix, std::move(proxy), + std::move(colorSpaceXform), filter, std::move(iter), dst); } }; #if GR_TEST_UTILS +#include "GrContextPriv.h" +#include "GrProxyProvider.h" /** Randomly divides subset into count divs. */ static void init_random_divs(int divs[], int count, int subsetStart, int subsetStop, @@ -239,7 +360,6 @@ static void init_random_divs(int divs[], int count, int subsetStart, int subsetS GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) { SkCanvas::Lattice lattice; - int imgW, imgH; // We loop because our random lattice code can produce an invalid lattice in the case where // there is a single div separator in both x and y and both are aligned with the left and top // edge of the image subset, respectively. @@ -248,19 +368,26 @@ GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) { std::unique_ptr<SkCanvas::Lattice::RectType[]> flags; std::unique_ptr<SkColor[]> colors; SkIRect subset; + GrSurfaceDesc desc; + desc.fConfig = kRGBA_8888_GrPixelConfig; + desc.fWidth = random->nextRangeU(1, 1000); + desc.fHeight = random->nextRangeU(1, 1000); + desc.fOrigin = + random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin; + auto proxy = context->contextPriv().proxyProvider()->createProxy( + desc, SkBackingFit::kExact, SkBudgeted::kYes); + do { - imgW = random->nextRangeU(1, 1000); - imgH = random->nextRangeU(1, 1000); if (random->nextBool()) { - subset.fLeft = random->nextULessThan(imgW); - subset.fRight = random->nextRangeU(subset.fLeft + 1, imgW); - subset.fTop = random->nextULessThan(imgH); - subset.fBottom = random->nextRangeU(subset.fTop + 1, imgH); + subset.fLeft = random->nextULessThan(desc.fWidth); + subset.fRight = random->nextRangeU(subset.fLeft + 1, desc.fWidth); + subset.fTop = random->nextULessThan(desc.fHeight); + subset.fBottom = random->nextRangeU(subset.fTop + 1, desc.fHeight); } else { - subset.setXYWH(0, 0, imgW, imgH); + subset.setXYWH(0, 0, desc.fWidth, desc.fHeight); } - // SkCanvas::Lattice allows bounds to be null. However, SkCanvas creates a temp Lattice with a - // non-null bounds before creating a SkLatticeIter since SkLatticeIter requires a bounds. + // SkCanvas::Lattice allows bounds to be null. However, SkCanvas creates a temp Lattice with + // a non-null bounds before creating a SkLatticeIter since SkLatticeIter requires a bounds. lattice.fBounds = ⊂ lattice.fXCount = random->nextRangeU(1, subset.width()); lattice.fYCount = random->nextRangeU(1, subset.height()); @@ -285,8 +412,7 @@ GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) { lattice.fRectTypes = nullptr; lattice.fColors = nullptr; } - } while (!SkLatticeIter::Valid(imgW, imgH, lattice)); - + } while (!SkLatticeIter::Valid(desc.fWidth, desc.fHeight, lattice)); SkRect dst; dst.fLeft = random->nextRangeScalar(-2000.5f, 1000.f); dst.fTop = random->nextRangeScalar(-2000.5f, 1000.f); @@ -294,7 +420,11 @@ GR_DRAW_OP_TEST_DEFINE(NonAALatticeOp) { dst.fBottom = dst.fTop + random->nextRangeScalar(0.5f, 1000.f); std::unique_ptr<SkLatticeIter> iter(new SkLatticeIter(lattice, dst)); SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random); - return NonAALatticeOp::Make(std::move(paint), viewMatrix, imgW, imgH, std::move(iter), dst); + auto csxf = GrTest::TestColorXform(random); + GrSamplerState::Filter filter = + random->nextBool() ? GrSamplerState::Filter::kNearest : GrSamplerState::Filter::kBilerp; + return NonAALatticeOp::Make(std::move(paint), viewMatrix, std::move(proxy), std::move(csxf), + filter, std::move(iter), dst); } #endif diff --git a/src/gpu/ops/GrLatticeOp.h b/src/gpu/ops/GrLatticeOp.h index cce8f322d8..ab3b8ea733 100644 --- a/src/gpu/ops/GrLatticeOp.h +++ b/src/gpu/ops/GrLatticeOp.h @@ -9,18 +9,21 @@ #define GLatticeOp_DEFINED #include <memory> -#include "GrTypes.h" +#include "GrSamplerState.h" +#include "SkRefCnt.h" class GrDrawOp; class GrPaint; class SkLatticeIter; +class GrTextureProxy; +class GrColorSpaceXform; class SkMatrix; struct SkRect; namespace GrLatticeOp { -std::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&& paint, const SkMatrix& viewMatrix, int imageWidth, - int imageHeight, std::unique_ptr<SkLatticeIter> iter, - const SkRect& dst); +std::unique_ptr<GrDrawOp> MakeNonAA(GrPaint&&, const SkMatrix& viewMatrix, sk_sp<GrTextureProxy>, + sk_sp<GrColorSpaceXform>, GrSamplerState::Filter, + std::unique_ptr<SkLatticeIter>, const SkRect& dst); }; #endif diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp index ad89e926f8..69f2d39e48 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -123,13 +123,9 @@ sk_sp<GrTextureProxy> SkImage_Gpu::asTextureProxyRef(GrContext* context, return nullptr; } - if (texColorSpace) { - *texColorSpace = this->fColorSpace; - } - GrTextureAdjuster adjuster(fContext, fProxy, this->alphaType(), this->uniqueID(), this->fColorSpace.get()); - return adjuster.refTextureProxySafeForParams(params, scaleAdjust); + return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust); } static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) { diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp index a92b751140..9d7e3b1c2b 100644 --- a/src/image/SkImage_Raster.cpp +++ b/src/image/SkImage_Raster.cpp @@ -178,16 +178,12 @@ sk_sp<GrTextureProxy> SkImage_Raster::asTextureProxyRef(GrContext* context, return nullptr; } - if (texColorSpace) { - *texColorSpace = sk_ref_sp(fBitmap.colorSpace()); - } - uint32_t uniqueID; sk_sp<GrTextureProxy> tex = this->refPinnedTextureProxy(&uniqueID); if (tex) { GrTextureAdjuster adjuster(context, fPinnedProxy, fBitmap.alphaType(), fPinnedUniqueID, fBitmap.colorSpace()); - return adjuster.refTextureProxySafeForParams(params, scaleAdjust); + return adjuster.refTextureProxyForParams(params, dstColorSpace, texColorSpace, scaleAdjust); } return GrRefCachedBitmapTextureProxy(context, fBitmap, params, scaleAdjust); |