diff options
author | Skia_Android Canary Bot <31977622648@project.gserviceaccount.com> | 2018-05-08 16:55:52 +0000 |
---|---|---|
committer | Leon Scroggins <scroggo@google.com> | 2018-05-08 17:23:27 +0000 |
commit | 84af2a4ff71f8b18c8f8c07613efd14a8b4faab5 (patch) | |
tree | a655d2d5c56ac43422abf23263ed819371500044 | |
parent | 5f24c982dd53c494bfb92a4c156c5768ba85664d (diff) | |
parent | 38784599f39026f54aa56b3c6e34afc15e00abd6 (diff) | |
download | skia-84af2a4ff71f8b18c8f8c07613efd14a8b4faab5.tar.gz |
Roll external/skia 149bd00d8..38784599f (3 commits)
https://skia.googlesource.com/skia.git/+log/149bd00d8..38784599f
2018-05-08 scroggo@google.com Cherry-pick of "Make GPU lattice/nine patch not bleed across cells."
2018-05-08 scroggo@google.com Make the src rects of truths in SkLatticeIter be integral.
2018-05-08 scroggo@google.com Reland "(Mostly) respect FilterQuality in draw[stretchy]"
The AutoRoll server is located here: https://android-next-roll.skia.org
Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md
If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.
Test: Presubmit checks will test this change.
Exempt-From-Owner-Approval: The autoroll bot does not require owner approval.
Bug: 77917978
Test: CtsUiRenderingTestCases
Change-Id: Ib7d0abdd51981bddf36ec5c3fd84bb651f405f0f
Merged-In: Iee8fe135636135e3635fb48c4bb2321213686cee
-rw-r--r-- | include/core/SkCanvas.h | 16 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 35 | ||||
-rw-r--r-- | src/core/SkLatticeIter.cpp | 11 | ||||
-rw-r--r-- | src/core/SkLatticeIter.h | 17 | ||||
-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 | 117 | ||||
-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 |
20 files changed, 410 insertions, 197 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 41f740a79b..221b05641a 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -1599,7 +1599,9 @@ public: If SkPaint paint is supplied, apply SkColorFilter, color alpha, SkImageFilter, SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader. - If paint contains SkMaskFilter, generate mask from image bounds. + If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint's + SkFilterQuality is higher than kLow_SkFilterQuality, it will be treated as if it + were kLow_SkFilterQuality. If generated mask extends beyond image bounds, replicate image edge colors, just as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set @@ -1728,7 +1730,9 @@ public: If SkPaint paint is supplied, apply SkColorFilter, color alpha, SkImageFilter, SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader. - If paint contains SkMaskFilter, generate mask from bitmap bounds. + If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint's + SkFilterQuality is higher than kLow_SkFilterQuality, it will be treated as if it + were kLow_SkFilterQuality. If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, just as SkShader made from SkShader::MakeBitmapShader with @@ -1828,7 +1832,9 @@ public: If SkPaint paint is supplied, apply SkColorFilter, color alpha, SkImageFilter, SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader. - If paint contains SkMaskFilter, generate mask from bitmap bounds. + If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint's + SkFilterQuality is higher than kLow_SkFilterQuality, it will be treated as if it + were kLow_SkFilterQuality. If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, just as SkShader made from SkShader::MakeBitmapShader with @@ -1856,7 +1862,9 @@ public: If SkPaint paint is supplied, apply SkColorFilter, color alpha, SkImageFilter, SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader. - If paint contains SkMaskFilter, generate mask from bitmap bounds. + If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint's + SkFilterQuality is higher than kLow_SkFilterQuality, it will be treated as if it + were kLow_SkFilterQuality. If generated mask extends beyond bitmap bounds, replicate bitmap edge colors, just as SkShader made from SkShader::MakeBitmapShader with diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 34b9d369ec..b29a538717 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1794,6 +1794,29 @@ void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPa constraint); } +namespace { +class NoneOrLowQualityFilterPaint : SkNoncopyable { +public: + NoneOrLowQualityFilterPaint(const SkPaint* origPaint) { + if (origPaint && origPaint->getFilterQuality() > kLow_SkFilterQuality) { + fLazyPaint.set(*origPaint); + fLazyPaint.get()->setFilterQuality(kLow_SkFilterQuality); + fPaint = fLazyPaint.get(); + } else { + fPaint = origPaint; + } + } + + const SkPaint* get() const { + return fPaint; + } + +private: + const SkPaint* fPaint; + SkLazyPaint fLazyPaint; +}; +} // namespace + void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { TRACE_EVENT0("skia", TRACE_FUNC); @@ -1802,7 +1825,8 @@ void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const return; } if (SkLatticeIter::Valid(image->width(), image->height(), center)) { - this->onDrawImageNine(image, center, dst, paint); + NoneOrLowQualityFilterPaint lowPaint(paint); + this->onDrawImageNine(image, center, dst, lowPaint.get()); } else { this->drawImageRect(image, dst, paint); } @@ -1824,7 +1848,8 @@ void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, co } if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) { - this->onDrawImageLattice(image, latticePlusBounds, dst, paint); + NoneOrLowQualityFilterPaint lowPaint(paint); + this->onDrawImageLattice(image, latticePlusBounds, dst, lowPaint.get()); } else { this->drawImageRect(image, dst, paint); } @@ -1865,7 +1890,8 @@ void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, con return; } if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) { - this->onDrawBitmapNine(bitmap, center, dst, paint); + NoneOrLowQualityFilterPaint lowPaint(paint); + this->onDrawBitmapNine(bitmap, center, dst, lowPaint.get()); } else { this->drawBitmapRect(bitmap, dst, paint); } @@ -1886,7 +1912,8 @@ void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, } if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) { - this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint); + NoneOrLowQualityFilterPaint lowPaint(paint); + this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, lowPaint.get()); } else { this->drawBitmapRect(bitmap, dst, paint); } diff --git a/src/core/SkLatticeIter.cpp b/src/core/SkLatticeIter.cpp index 434cce6e11..fcc12c6f21 100644 --- a/src/core/SkLatticeIter.cpp +++ b/src/core/SkLatticeIter.cpp @@ -76,10 +76,9 @@ static int count_scalable_pixels(const int32_t* divs, int numDivs, bool firstIsS /** * Set points for the src and dst rects on subsequent draw calls. */ -static void set_points(float* dst, float* src, const int* divs, int divCount, int srcFixed, - int srcScalable, float srcStart, float srcEnd, float dstStart, float dstEnd, +static void set_points(float* dst, int* src, const int* divs, int divCount, int srcFixed, + int srcScalable, int srcStart, int srcEnd, float dstStart, float dstEnd, bool isScalable) { - float dstLen = dstEnd - dstStart; float scale; if (srcFixed <= dstLen) { @@ -94,8 +93,8 @@ static void set_points(float* dst, float* src, const int* divs, int divCount, in src[0] = srcStart; dst[0] = dstStart; for (int i = 0; i < divCount; i++) { - src[i + 1] = (float) (divs[i]); - float srcDelta = src[i + 1] - src[i]; + src[i + 1] = divs[i]; + int srcDelta = src[i + 1] - src[i]; float dstDelta; if (srcFixed <= dstLen) { dstDelta = isScalable ? scale * srcDelta : srcDelta; @@ -254,7 +253,7 @@ SkLatticeIter::SkLatticeIter(int w, int h, const SkIRect& c, const SkRect& dst) fNumRectsToDraw = 9; } -bool SkLatticeIter::next(SkRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) { +bool SkLatticeIter::next(SkIRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) { int currRect = fCurrX + fCurrY * (fSrcX.count() - 1); if (currRect == fNumRectsInLattice) { return false; diff --git a/src/core/SkLatticeIter.h b/src/core/SkLatticeIter.h index 08cdd5a965..afd0c39742 100644 --- a/src/core/SkLatticeIter.h +++ b/src/core/SkLatticeIter.h @@ -34,9 +34,20 @@ public: * isFixedColor and fixedColor specify if the rectangle is filled with a fixed color. * If (*isFixedColor) is true, then (*fixedColor) contains the rectangle color. */ - bool next(SkRect* src, SkRect* dst, bool* isFixedColor = nullptr, + bool next(SkIRect* src, SkRect* dst, bool* isFixedColor = nullptr, SkColor* fixedColor = nullptr); + /** Version of above that converts the integer src rect to a scalar rect. */ + bool next(SkRect* src, SkRect* dst, bool* isFixedColor = nullptr, + SkColor* fixedColor = nullptr) { + SkIRect isrcR; + if (this->next(&isrcR, dst, isFixedColor, fixedColor)) { + *src = SkRect::Make(isrcR); + return true; + } + return false; + } + /** * Apply a matrix to the dst points. */ @@ -50,8 +61,8 @@ public: } private: - SkTArray<SkScalar> fSrcX; - SkTArray<SkScalar> fSrcY; + SkTArray<int> fSrcX; + SkTArray<int> fSrcY; SkTArray<SkScalar> fDstX; SkTArray<SkScalar> fDstY; SkTArray<SkCanvas::Lattice::RectType> fRectTypes; 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 b7ba1d40a8..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. @@ -1352,66 +1354,34 @@ void SkGpuDevice::drawImageRect(const SkImage* image, const SkRect* src, const S } } -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; - } - - static const GrSamplerState::Filter kMode = GrSamplerState::Filter::kNearest; - 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; +// When drawing nine-patches or n-patches, cap the filter quality at kBilerp. +static GrSamplerState::Filter compute_lattice_filter_mode(const SkPaint& paint) { + if (paint.getFilterQuality() == kNone_SkFilterQuality) { + return GrSamplerState::Filter::kNearest; } - 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); + return GrSamplerState::Filter::kBilerp; } 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); } } } @@ -1419,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); - static const GrSamplerState::Filter kMode = GrSamplerState::Filter::kNearest; - 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, @@ -1455,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); } } } @@ -1476,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); |