Revert "Remove copies for wrap modes in GrTextureProducer."
This reverts commit 7fba244ea9d446eb8e4b36f9c3acc161b3db6dcf.
Reason for revert: See if this is blocking the Chrome roll
Original change's description:
> Remove copies for wrap modes in GrTextureProducer.
>
> GrTextureEffect now supports implementing wrap modes in shaders
> for subsets and texture types with HW sampling restrictions.
>
> Change-Id: I5c93ade044465e13c5f56f7437fbbe288db0a8a8
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271056
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
TBR=egdaniel@google.com,bsalomon@google.com
Change-Id: I14397bec8ff4ba165c28faa8f44497f47d865862
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272522
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index ee610f3..28e0bac 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -273,8 +273,8 @@
}
static void draw_as_tex(SkCanvas* canvas, SkImage* image, SkScalar x, SkScalar y) {
- GrSurfaceProxyView view =
- as_IB(image)->refView(canvas->getGrContext(), GrSamplerState::Filter::kBilerp);
+ GrSurfaceProxyView view = as_IB(image)->refView(canvas->getGrContext(),
+ GrSamplerState::Filter::kBilerp, nullptr);
if (!view) {
// show placeholder if we have no texture
SkPaint paint;
diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp
index 957aebb..e3a9eb5 100644
--- a/src/gpu/GrBitmapTextureMaker.cpp
+++ b/src/gpu/GrBitmapTextureMaker.cpp
@@ -122,14 +122,13 @@
return {};
}
-void GrBitmapTextureMaker::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
+void GrBitmapTextureMaker::makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) {
// Destination color space is irrelevant - we always upload the bitmap's contents as-is
if (fOriginalKey.isValid()) {
- MakeMipMappedKeyFromOriginalKey(fOriginalKey, mipMappedKey);
+ MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey);
}
}
-void GrBitmapTextureMaker::didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey,
- uint32_t contextUniqueID) {
- GrInstallBitmapUniqueKeyInvalidator(mipMappedKey, contextUniqueID, fBitmap.pixelRef());
+void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
+ GrInstallBitmapUniqueKeyInvalidator(copyKey, contextUniqueID, fBitmap.pixelRef());
}
diff --git a/src/gpu/GrBitmapTextureMaker.h b/src/gpu/GrBitmapTextureMaker.h
index 72475ca..1090a75 100644
--- a/src/gpu/GrBitmapTextureMaker.h
+++ b/src/gpu/GrBitmapTextureMaker.h
@@ -26,8 +26,8 @@
GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
AllowedTexGenType onlyIfFast) override;
- void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
- void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override;
+ void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) override;
+ void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
const SkBitmap fBitmap;
const SkBackingFit fFit;
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 0eca489..65829eb 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -45,14 +45,61 @@
////////////////////////////////////////////////////////////////////////////////
-bool GrGpu::IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy,
- GrSamplerState::Filter filter) {
- SkASSERT(texProxy);
- if (filter != GrSamplerState::Filter::kMipMap || texProxy->mipMapped() == GrMipMapped::kYes ||
- !caps->mipMapSupport()) {
- return false;
+bool GrGpu::IsACopyNeededForRepeatWrapMode(const GrCaps* caps,
+ GrTextureProxy* texProxy,
+ SkISize dimensions,
+ GrSamplerState::Filter filter,
+ GrTextureProducer::CopyParams* copyParams,
+ SkScalar scaleAdjust[2]) {
+ if (!caps->npotTextureTileSupport() &&
+ (!SkIsPow2(dimensions.width()) || !SkIsPow2(dimensions.height()))) {
+ SkASSERT(scaleAdjust);
+ copyParams->fDimensions = {SkNextPow2(dimensions.width()), SkNextPow2(dimensions.height())};
+ SkASSERT(scaleAdjust);
+ scaleAdjust[0] = ((SkScalar)copyParams->fDimensions.width()) / dimensions.width();
+ scaleAdjust[1] = ((SkScalar)copyParams->fDimensions.height()) / dimensions.height();
+ switch (filter) {
+ case GrSamplerState::Filter::kNearest:
+ copyParams->fFilter = GrSamplerState::Filter::kNearest;
+ break;
+ case GrSamplerState::Filter::kBilerp:
+ case GrSamplerState::Filter::kMipMap:
+ // We are only ever scaling up so no reason to ever indicate kMipMap.
+ copyParams->fFilter = GrSamplerState::Filter::kBilerp;
+ break;
+ }
+ return true;
}
- return SkMipMap::ComputeLevelCount(texProxy->width(), texProxy->height()) > 0;
+
+ if (texProxy) {
+ // If the texture format itself doesn't support repeat wrap mode or mipmapping (and
+ // those capabilities are required) force a copy.
+ if (texProxy->hasRestrictedSampling()) {
+ copyParams->fFilter = GrSamplerState::Filter::kNearest;
+ copyParams->fDimensions = texProxy->dimensions();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool GrGpu::IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy,
+ GrSamplerState::Filter filter,
+ GrTextureProducer::CopyParams* copyParams) {
+ SkASSERT(texProxy);
+ int mipCount = SkMipMap::ComputeLevelCount(texProxy->width(), texProxy->height());
+ bool willNeedMips = GrSamplerState::Filter::kMipMap == filter && caps->mipMapSupport() &&
+ mipCount;
+ // If the texture format itself doesn't support mipmapping (and those capabilities are required)
+ // force a copy.
+ if (willNeedMips && texProxy->mipMapped() == GrMipMapped::kNo) {
+ copyParams->fFilter = GrSamplerState::Filter::kNearest;
+ copyParams->fDimensions = texProxy->dimensions();
+ return true;
+ }
+
+ return false;
}
static bool validate_texel_levels(SkISize dimensions, GrColorType texelColorType,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 6969d41..5551e6e 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -594,12 +594,22 @@
virtual GrStencilAttachment* createStencilAttachmentForRenderTarget(
const GrRenderTarget*, int width, int height, int numStencilSamples) = 0;
+ // Determines whether a texture will need to be rescaled in order to be used with the
+ // GrSamplerState.
+ static bool IsACopyNeededForRepeatWrapMode(const GrCaps*,
+ GrTextureProxy* texProxy,
+ SkISize dimensions,
+ GrSamplerState::Filter,
+ GrTextureProducer::CopyParams*,
+ SkScalar scaleAdjust[2]);
+
// Determines whether a texture will need to be copied because the draw requires mips but the
// texutre doesn't have any. This call should be only checked if IsACopyNeededForTextureParams
// fails. If the previous call succeeds, then a copy should be done using those params and the
// mip mapping requirements will be handled there.
static bool IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy,
- GrSamplerState::Filter filter);
+ GrSamplerState::Filter filter,
+ GrTextureProducer::CopyParams* copyParams);
void handleDirtyContext() {
if (fResetBits) {
diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp
index f531fed..8361f6a 100644
--- a/src/gpu/GrImageTextureMaker.cpp
+++ b/src/gpu/GrImageTextureMaker.cpp
@@ -39,14 +39,15 @@
onlyIfFast);
}
-void GrImageTextureMaker::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
+void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
if (fOriginalKey.isValid() && SkImage::kAllow_CachingHint == fCachingHint) {
GrUniqueKey cacheKey;
fImage->makeCacheKeyFromOrigKey(fOriginalKey, &cacheKey);
- MakeMipMappedKeyFromOriginalKey(cacheKey, mipMappedKey);
+ MakeCopyKeyFromOrigKey(cacheKey, stretch, paramsCopyKey);
}
}
+
/////////////////////////////////////////////////////////////////////////////////////////////////
GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client,
@@ -74,13 +75,13 @@
}
}
-void GrYUVAImageTextureMaker::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
+void GrYUVAImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
// TODO: Do we ever want to disable caching?
if (fOriginalKey.isValid()) {
GrUniqueKey cacheKey;
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey::Builder builder(&cacheKey, fOriginalKey, kDomain, 0, "Image");
- MakeMipMappedKeyFromOriginalKey(cacheKey, mipMappedKey);
+ MakeCopyKeyFromOrigKey(cacheKey, stretch, paramsCopyKey);
}
}
diff --git a/src/gpu/GrImageTextureMaker.h b/src/gpu/GrImageTextureMaker.h
index 87e505d..1bfea5a 100644
--- a/src/gpu/GrImageTextureMaker.h
+++ b/src/gpu/GrImageTextureMaker.h
@@ -22,12 +22,14 @@
SkImage::CachingHint chint, bool useDecal = false);
private:
+ // TODO: consider overriding this, for the case where the underlying generator might be
+ // able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
+ // GrTexture* generateTextureForParams(const CopyParams&) override;
GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
AllowedTexGenType onlyIfFast) override;
- void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
- void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override {
- }
+ void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
+ void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
const SkImage_Lazy* fImage;
GrUniqueKey fOriginalKey;
@@ -51,9 +53,8 @@
GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
AllowedTexGenType onlyIfFast) override;
- void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
- void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override {
- }
+ void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
+ void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
const SkMatrix& textureMatrix,
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
index 6d4628a..96b0b64 100644
--- a/src/gpu/GrTextureAdjuster.cpp
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -22,47 +22,65 @@
, fOriginal(std::move(original))
, fUniqueID(uniqueID) {}
-void GrTextureAdjuster::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
+void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
// Destination color space is irrelevant - we already have a texture so we're just sub-setting
GrUniqueKey baseKey;
GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeSize(this->dimensions()));
- MakeMipMappedKeyFromOriginalKey(baseKey, mipMappedKey);
+ MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
}
-void GrTextureAdjuster::didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey,
- uint32_t contextUniqueID) {
+void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
// We don't currently have a mechanism for notifications on Images!
}
-GrSurfaceProxyView GrTextureAdjuster::makeMippedCopy() {
+GrSurfaceProxyView GrTextureAdjuster::copy(const CopyParams& copyParams, bool willBeMipped,
+ bool copyForMipsOnly) {
GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
GrUniqueKey key;
- this->makeMipMappedKey(&key);
+ this->makeCopyKey(copyParams, &key);
sk_sp<GrTextureProxy> cachedCopy;
const GrSurfaceProxyView& originalView = this->originalProxyView();
if (key.isValid()) {
cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key, this->colorType());
- if (cachedCopy) {
- return {std::move(cachedCopy), originalView.origin(), originalView.swizzle()};
+ if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
+ // TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
+ // colorTypes, we can use the swizzle of the originalView.
+ GrSwizzle swizzle = cachedCopy->textureSwizzleDoNotUse();
+ return GrSurfaceProxyView(std::move(cachedCopy), originalView.origin(), swizzle);
}
}
- GrSurfaceProxyView copyView = GrCopyBaseMipMapToTextureProxy(
- this->context(), originalView.proxy(), originalView.origin(), this->colorType());
- if (!copyView) {
- return {};
+ GrSurfaceProxyView copyView;
+ if (copyForMipsOnly) {
+ copyView = GrCopyBaseMipMapToTextureProxy(this->context(), originalView.proxy(),
+ originalView.origin(), this->colorType());
+ } else {
+ copyView = CopyOnGpu(this->context(), this->originalProxyViewRef(), this->colorType(),
+ copyParams, willBeMipped);
}
- if (key.isValid()) {
- SkASSERT(copyView.origin() == originalView.origin());
- proxyProvider->assignUniqueKeyToProxy(key, copyView.asTextureProxy());
- this->didCacheMipMappedCopy(key, proxyProvider->contextID());
+ if (copyView.proxy()) {
+ if (key.isValid()) {
+ SkASSERT(copyView.origin() == originalView.origin());
+ if (cachedCopy) {
+ SkASSERT(GrMipMapped::kYes == copyView.asTextureProxy()->mipMapped() &&
+ GrMipMapped::kNo == cachedCopy->mipMapped());
+ // If we had a cachedProxy, that means there already is a proxy in the cache which
+ // matches the key, but it does not have mip levels and we require them. Thus we
+ // must remove the unique key from that proxy.
+ SkASSERT(cachedCopy->getUniqueKey() == key);
+ proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
+ }
+ proxyProvider->assignUniqueKeyToProxy(key, copyView.asTextureProxy());
+ this->didCacheCopy(key, proxyProvider->contextID());
+ }
}
return copyView;
}
GrSurfaceProxyView GrTextureAdjuster::onRefTextureProxyViewForParams(GrSamplerState params,
- bool willBeMipped) {
+ bool willBeMipped,
+ SkScalar scaleAdjust[2]) {
if (this->context()->priv().abandoned()) {
// The texture was abandoned.
return {};
@@ -74,32 +92,51 @@
GrSurfaceProxyView view = this->originalProxyViewRef();
GrTextureProxy* texProxy = view.asTextureProxy();
SkASSERT(texProxy);
- if (!GrGpu::IsACopyNeededForMips(this->context()->priv().caps(), texProxy, params.filter())) {
- return view;
+ CopyParams copyParams;
+
+ bool needsCopyForMipsOnly = false;
+ if (!params.isRepeated() ||
+ !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
+ texProxy->dimensions(), params.filter(), ©Params,
+ scaleAdjust)) {
+ needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
+ texProxy, params.filter(),
+ ©Params);
+ if (!needsCopyForMipsOnly) {
+ return view;
+ }
}
- GrSurfaceProxyView copy = this->makeMippedCopy();
- if (!copy) {
+ GrSurfaceProxyView result = this->copy(copyParams, willBeMipped, needsCopyForMipsOnly);
+ if (!result.proxy() && needsCopyForMipsOnly) {
// If we were unable to make a copy and we only needed a copy for mips, then we will return
// the source texture here and require that the GPU backend is able to fall back to using
// bilerp if mips are required.
return view;
}
- SkASSERT(copy.asTextureProxy());
- return copy;
+ SkASSERT(result.asTextureProxy());
+ return result;
}
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
- const SkMatrix& textureMatrix,
+ const SkMatrix& origTextureMatrix,
const SkRect& constraintRect,
FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
const GrSamplerState::Filter* filterOrNullForBicubic) {
- GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic);
- if (!view) {
+ SkMatrix textureMatrix = origTextureMatrix;
+
+ SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
+ GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic, scaleAdjust);
+ if (!view.proxy()) {
return nullptr;
}
SkASSERT(view.asTextureProxy());
+ // If we made a copy then we only copied the contentArea, in which case the new texture is all
+ // content.
+ if (view.proxy() != this->originalProxyView().proxy()) {
+ textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
+ }
SkRect domain;
DomainMode domainMode =
diff --git a/src/gpu/GrTextureAdjuster.h b/src/gpu/GrTextureAdjuster.h
index d52e517..bb34c5d 100644
--- a/src/gpu/GrTextureAdjuster.h
+++ b/src/gpu/GrTextureAdjuster.h
@@ -33,16 +33,17 @@
uint32_t uniqueID, bool useDecal = false);
protected:
- void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
- void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override;
+ void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) override;
+ void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
const GrSurfaceProxyView& originalProxyView() const { return fOriginal; }
GrSurfaceProxyView originalProxyViewRef() const { return fOriginal; }
private:
- GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped) override;
+ GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped,
+ SkScalar scaleAdjust[2]) override;
- GrSurfaceProxyView makeMippedCopy();
+ GrSurfaceProxyView copy(const CopyParams& copyParams, bool willBeMipped, bool copyOnlyForMips);
GrSurfaceProxyView fOriginal;
uint32_t fUniqueID;
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index d9e89c2..17200f2 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -14,66 +14,102 @@
#include "src/gpu/GrRecordingContextPriv.h"
GrSurfaceProxyView GrTextureMaker::onRefTextureProxyViewForParams(GrSamplerState params,
- bool willBeMipped) {
+ bool willBeMipped,
+ SkScalar scaleAdjust[2]) {
if (this->width() > this->context()->priv().caps()->maxTextureSize() ||
this->height() > this->context()->priv().caps()->maxTextureSize()) {
return {};
}
+ CopyParams copyParams;
+
GrSurfaceProxyView original = this->refOriginalTextureProxyView(willBeMipped,
AllowedTexGenType::kCheap);
- if (!original) {
- return this->refOriginalTextureProxyView(willBeMipped, AllowedTexGenType::kAny);
- }
-
- GrTextureProxy* texProxy = original.asTextureProxy();
- if (!GrGpu::IsACopyNeededForMips(this->context()->priv().caps(), texProxy, params.filter())) {
- return original;
+ bool needsCopyForMipsOnly = false;
+ if (original.proxy()) {
+ GrTextureProxy* texProxy = original.asTextureProxy();
+ SkASSERT(texProxy);
+ if (!params.isRepeated() ||
+ !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
+ texProxy->dimensions(), params.filter(),
+ ©Params, scaleAdjust)) {
+ needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
+ texProxy, params.filter(),
+ ©Params);
+ if (!needsCopyForMipsOnly) {
+ return original;
+ }
+ }
+ } else {
+ if (!params.isRepeated() ||
+ !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), nullptr,
+ this->dimensions(), params.filter(), ©Params,
+ scaleAdjust)) {
+ return this->refOriginalTextureProxyView(willBeMipped, AllowedTexGenType::kAny);
+ }
}
GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
GrSurfaceOrigin origOrigin = original.proxy() ? original.origin() : kTopLeft_GrSurfaceOrigin;
- GrUniqueKey mipMappedKey;
- this->makeMipMappedKey(&mipMappedKey);
- if (mipMappedKey.isValid()) {
- auto cachedProxy =
- proxyProvider->findOrCreateProxyByUniqueKey(mipMappedKey, this->colorType());
+ GrUniqueKey copyKey;
+ this->makeCopyKey(copyParams, ©Key);
+ GrSurfaceProxyView cachedView;
+ if (copyKey.isValid()) {
+ auto cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, this->colorType());
if (cachedProxy) {
- SkASSERT(cachedProxy->mipMapped() == GrMipMapped::kYes);
- // TODO: Once we no longer use MakeMipMappedCopy which can fallback to arbitrary formats
- // and colorTypes, we can use the swizzle of the originalView.
+ GrMipMapped mipped = cachedProxy->mipMapped();
+ // TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
+ // colorTypes, we can use the swizzle of the originalView.
GrSwizzle swizzle = cachedProxy->textureSwizzleDoNotUse();
- return GrSurfaceProxyView(std::move(cachedProxy), origOrigin, swizzle);
+ cachedView = GrSurfaceProxyView(std::move(cachedProxy), origOrigin, swizzle);
+ if (!willBeMipped || GrMipMapped::kYes == mipped) {
+ return cachedView;
+ }
}
}
GrSurfaceProxyView source;
- if (original) {
+ if (original.proxy()) {
source = std::move(original);
+ } else if (cachedView.proxy()) {
+ source = cachedView;
} else {
// Since we will be copying this texture there is no reason to make it mipped
source = this->refOriginalTextureProxyView(false, AllowedTexGenType::kAny);
- if (!source) {
- return {};
- }
}
+ if (!source.proxy()) {
+ return {};
+ }
SkASSERT(source.asTextureProxy());
- GrSurfaceProxyView result = MakeMipMappedCopy(this->context(), source, this->colorType());
+ GrSurfaceProxyView result =
+ CopyOnGpu(this->context(), source, this->colorType(), copyParams, willBeMipped);
- if (!result) {
+ if (!result.proxy()) {
// If we were unable to make a copy and we only needed a copy for mips, then we will return
// the source texture here and require that the GPU backend is able to fall back to using
// bilerp if mips are required.
- return source;
+ if (needsCopyForMipsOnly) {
+ return source;
+ }
+ return {};
}
- if (mipMappedKey.isValid()) {
+ if (copyKey.isValid()) {
SkASSERT(result.origin() == origOrigin);
- proxyProvider->assignUniqueKeyToProxy(mipMappedKey, result.asTextureProxy());
- this->didCacheMipMappedCopy(mipMappedKey, proxyProvider->contextID());
+ if (cachedView.proxy()) {
+ SkASSERT(GrMipMapped::kYes == result.asTextureProxy()->mipMapped() &&
+ GrMipMapped::kNo == cachedView.asTextureProxy()->mipMapped());
+ // If we had a cachedProxy, that means there already is a proxy in the cache which
+ // matches the key, but it does not have mip levels and we require them. Thus we must
+ // remove the unique key from that proxy.
+ SkASSERT(cachedView.asTextureProxy()->getUniqueKey() == copyKey);
+ proxyProvider->removeUniqueKeyFromProxy(cachedView.asTextureProxy());
+ }
+ proxyProvider->assignUniqueKeyToProxy(copyKey, result.asTextureProxy());
+ this->didCacheCopy(copyKey, proxyProvider->contextID());
}
return result;
}
@@ -96,10 +132,13 @@
fmForDetermineDomain = &kBilerp;
}
- GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic);
- if (!view) {
+ SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
+ GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic, scaleAdjust);
+ if (!view.proxy()) {
return nullptr;
}
+ SkMatrix adjustedMatrix = textureMatrix;
+ adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
SkRect domain;
DomainMode domainMode =
@@ -107,5 +146,5 @@
view.proxy(), fmForDetermineDomain, &domain);
SkASSERT(kTightCopy_DomainMode != domainMode);
return this->createFragmentProcessorForDomainAndFilter(
- std::move(view), textureMatrix, domainMode, domain, filterOrNullForBicubic);
+ std::move(view), adjustedMatrix, domainMode, domain, filterOrNullForBicubic);
}
diff --git a/src/gpu/GrTextureMaker.h b/src/gpu/GrTextureMaker.h
index 6296964..22aaced 100644
--- a/src/gpu/GrTextureMaker.h
+++ b/src/gpu/GrTextureMaker.h
@@ -40,7 +40,9 @@
AllowedTexGenType genType) = 0;
private:
- GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped) override;
+ GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState,
+ bool willBeMipped,
+ SkScalar scaleAdjust[2]) override;
typedef GrTextureProducer INHERITED;
};
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index 55fccc0..0e2f908 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -21,35 +21,53 @@
#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/effects/GrTextureEffect.h"
-GrSurfaceProxyView GrTextureProducer::MakeMipMappedCopy(GrRecordingContext* context,
- GrSurfaceProxyView inputView,
- GrColorType colorType) {
+GrSurfaceProxyView GrTextureProducer::CopyOnGpu(GrRecordingContext* context,
+ GrSurfaceProxyView inputView,
+ GrColorType colorType,
+ const CopyParams& copyParams,
+ bool dstWillRequireMipMaps) {
SkASSERT(context);
SkASSERT(inputView.asTextureProxy());
- GrSurfaceProxy* proxy = inputView.proxy();
- SkRect proxyRect = proxy->getBoundsRect();
+ const SkRect dstRect = SkRect::Make(copyParams.fDimensions);
+ GrMipMapped mipMapped = dstWillRequireMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
- GrSurfaceProxyView view =
- GrCopyBaseMipMapToTextureProxy(context, proxy, inputView.origin(), colorType);
- if (view) {
- return view;
+ GrSurfaceProxy* proxy = inputView.proxy();
+ SkRect localRect = proxy->getBoundsRect();
+
+ bool resizing = false;
+ if (copyParams.fFilter != GrSamplerState::Filter::kNearest) {
+ resizing = localRect.width() != dstRect.width() || localRect.height() != dstRect.height();
+ }
+
+ if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !resizing &&
+ dstWillRequireMipMaps) {
+ GrSurfaceProxyView view = GrCopyBaseMipMapToTextureProxy(context, proxy, inputView.origin(),
+ colorType);
+ if (view.proxy()) {
+ return view;
+ }
}
auto copyRTC = GrRenderTargetContext::MakeWithFallback(
- context, colorType, nullptr, SkBackingFit::kExact, inputView.dimensions(), 1,
- GrMipMapped::kYes, proxy->isProtected(), inputView.origin());
+ context, colorType, nullptr, SkBackingFit::kExact, copyParams.fDimensions, 1,
+ mipMapped, proxy->isProtected(), inputView.origin());
if (!copyRTC) {
return {};
}
+ const auto& caps = *context->priv().caps();
GrPaint paint;
- auto fp = GrTextureEffect::Make(std::move(inputView), kUnknown_SkAlphaType, SkMatrix::I(),
- GrSamplerState::Filter::kNearest);
+
+ GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, copyParams.fFilter);
+ auto boundsRect = SkRect::Make(proxy->dimensions());
+ auto fp = GrTextureEffect::MakeSubset(std::move(inputView), kUnknown_SkAlphaType, SkMatrix::I(),
+ sampler, boundsRect, localRect, caps);
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- copyRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), proxyRect);
+ copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
+ localRect);
return copyRTC->readSurfaceView();
}
@@ -200,7 +218,7 @@
}
GrSurfaceProxyView GrTextureProducer::viewForParams(
- const GrSamplerState::Filter* filterOrNullForBicubic) {
+ const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]) {
GrSamplerState sampler; // Default is nearest + clamp
if (filterOrNullForBicubic) {
sampler.setFilterMode(*filterOrNullForBicubic);
@@ -212,29 +230,36 @@
sampler.setWrapModeY(GrSamplerState::WrapMode::kClampToBorder);
}
}
- return this->viewForParams(sampler);
+ return this->viewForParams(sampler, scaleAdjust);
}
-GrSurfaceProxyView GrTextureProducer::viewForParams(GrSamplerState sampler) {
+GrSurfaceProxyView GrTextureProducer::viewForParams(GrSamplerState sampler,
+ SkScalar scaleAdjust[2]) {
+ // Check that the caller pre-initialized scaleAdjust
+ SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1));
+
const GrCaps* caps = this->context()->priv().caps();
int mipCount = SkMipMap::ComputeLevelCount(this->width(), this->height());
bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount &&
caps->mipMapSupport();
- auto result = this->onRefTextureProxyViewForParams(sampler, willBeMipped);
- if (!result) {
- return {};
- }
-
- SkASSERT(result.asTextureProxy());
+ auto result = this->onRefTextureProxyViewForParams(sampler, willBeMipped, scaleAdjust);
// Check to make sure that if we say the texture willBeMipped that the returned texture has mip
// maps, unless the config is not copyable.
- SkASSERT(!willBeMipped || result.asTextureProxy()->mipMapped() == GrMipMapped::kYes ||
+ SkASSERT(!result.proxy() || !willBeMipped ||
+ result.asTextureProxy()->mipMapped() == GrMipMapped::kYes ||
!caps->isFormatCopyable(result.proxy()->backendFormat()));
- SkASSERT(result.proxy()->dimensions() == this->dimensions());
+ SkASSERT(!result.proxy() || result.asTextureProxy());
+
+ SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap &&
+ !sampler.isRepeated()));
+ // Check that the "no scaling expected" case always returns a proxy of the same size as the
+ // producer.
+ SkASSERT(!result.proxy() || !expectNoScale ||
+ result.proxy()->dimensions() == this->dimensions());
return result;
}
@@ -245,7 +270,7 @@
: GrSamplerState::Filter::kMipMap;
GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, filter);
- auto result = this->viewForParams(sampler);
+ auto result = this->viewForParams(sampler, nullptr);
#ifdef SK_DEBUG
const GrCaps* caps = this->context()->priv().caps();
diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h
index a1a9a02..39944d9 100644
--- a/src/gpu/GrTextureProducer.h
+++ b/src/gpu/GrTextureProducer.h
@@ -32,6 +32,11 @@
*/
class GrTextureProducer : public SkNoncopyable {
public:
+ struct CopyParams {
+ GrSamplerState::Filter fFilter;
+ SkISize fDimensions;
+ };
+
enum FilterConstraint {
kYes_FilterConstraint,
kNo_FilterConstraint,
@@ -66,10 +71,21 @@
/**
* 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).
*/
- GrSurfaceProxyView viewForParams(GrSamplerState);
+ GrSurfaceProxyView viewForParams(GrSamplerState, SkScalar scaleAdjust[2]);
- GrSurfaceProxyView viewForParams(const GrSamplerState::Filter* filterOrNullForBicubic);
+ GrSurfaceProxyView viewForParams(const GrSamplerState::Filter* filterOrNullForBicubic,
+ SkScalar scaleAdjust[2]);
/**
* Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have
@@ -105,29 +121,35 @@
GrColorType colorType() const { return fImageInfo.colorType(); }
/** Helper for creating a key for a copy from an original key. */
- static void MakeMipMappedKeyFromOriginalKey(const GrUniqueKey& origKey,
- GrUniqueKey* mipMappedKey) {
- SkASSERT(!mipMappedKey->isValid());
+ static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
+ const CopyParams& copyParams,
+ GrUniqueKey* copyKey) {
+ SkASSERT(!copyKey->isValid());
if (origKey.isValid()) {
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(mipMappedKey, origKey, kDomain, 0);
+ GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
+ builder[0] = static_cast<uint32_t>(copyParams.fFilter);
+ builder[1] = copyParams.fDimensions.width();
+ builder[2] = copyParams.fDimensions.height();
}
}
/**
- * If we need to make a copy with MIP maps the producer is asked to return a key that identifies
- * the original conteny + the addition of MIP map levels. If the producer does not want to cache
- * the copy it can simply leave the key uninitialized.
- */
- virtual void makeMipMappedKey(GrUniqueKey* mipMappedKey) = 0;
+ * If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
+ * return a key that identifies its original content + the CopyParms parameter. If the producer
+ * does not want to cache the stretched version (e.g. the producer is volatile), this should
+ * simply return without initializing the copyKey. If the texture generated by this producer
+ * depends on the destination color space, then that information should also be incorporated
+ * in the key.
+ */
+ virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;
/**
- * If a stretched version of the texture is generated, it may be cached (assuming that
- * makeMipMappedKey() returns true). In that case, the maker is notified in case it
- * wants to note that for when the maker is destroyed.
- */
- virtual void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey,
- uint32_t contextUniqueID) = 0;
+ * If a stretched version of the texture is generated, it may be cached (assuming that
+ * makeCopyKey() returns true). In that case, the maker is notified in case it
+ * wants to note that for when the maker is destroyed.
+ */
+ virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0;
enum DomainMode {
kNoDomain_DomainMode,
@@ -135,11 +157,12 @@
kTightCopy_DomainMode
};
- // TODO: Try to remove the draw fallback and directly use GrCopyBaseMipMapToTextureProxy
- // instead.
- static GrSurfaceProxyView MakeMipMappedCopy(GrRecordingContext*,
- GrSurfaceProxyView,
- GrColorType colorType);
+ // This can draw to accomplish the copy, thus the recording context is needed
+ static GrSurfaceProxyView CopyOnGpu(GrRecordingContext*,
+ GrSurfaceProxyView inputView,
+ GrColorType,
+ const CopyParams& copyParams,
+ bool dstWillRequireMipMaps);
static DomainMode DetermineDomainMode(const SkRect& constraintRect,
FilterConstraint filterConstraint,
@@ -158,8 +181,8 @@
GrRecordingContext* context() const { return fContext; }
private:
- virtual GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState,
- bool willBeMipped) = 0;
+ virtual GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped,
+ SkScalar scaleAdjust[2]) = 0;
GrRecordingContext* fContext;
const GrImageInfo fImageInfo;
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 9deaff9..d52787e 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -918,13 +918,15 @@
bitmap.height() <= this->caps()->maxTileSize());
SkASSERT(!samplerState.isRepeated());
- GrSurfaceProxyView view = GrRefCachedBitmapView(fContext.get(), bitmap, samplerState);
+ SkScalar scales[2] = {1.f, 1.f};
+ GrSurfaceProxyView view = GrRefCachedBitmapView(fContext.get(), bitmap, samplerState, scales);
if (!view) {
return;
}
// Compute a matrix that maps the rect we will draw to the src rect.
SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
+ texMatrix.postScale(scales[0], scales[1]);
SkAlphaType srcAlphaType = bitmap.alphaType();
@@ -1050,7 +1052,7 @@
auto filter = paint.getFilterQuality() > kNone_SkFilterQuality
? GrSamplerState::Filter::kBilerp
: GrSamplerState::Filter::kNearest;
- GrSurfaceProxyView clipView = as_IB(clipImage)->refView(this->context(), filter);
+ GrSurfaceProxyView clipView = as_IB(clipImage)->refView(this->context(), filter, nullptr);
// Fold clip matrix into ctm
ctm.preConcat(clipMatrix);
SkMatrix inverseClipMatrix;
@@ -1343,7 +1345,7 @@
auto dstColorSpace = fRenderTargetContext->colorInfo().colorSpace();
const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint);
- auto view = producer->viewForParams(&filter);
+ auto view = producer->viewForParams(&filter, nullptr);
if (!view) {
return;
}
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 7b2b1a9..edd3469 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -537,7 +537,7 @@
uint32_t uniqueID;
view = image->refPinnedView(this->context(), &uniqueID);
if (!view) {
- view = image->refView(this->context(), GrSamplerState::Filter::kBilerp);
+ view = image->refView(this->context(), GrSamplerState::Filter::kBilerp, nullptr);
}
}
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 0b20bb7..c6fb7b7 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -134,9 +134,9 @@
}
GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext* ctx, const SkBitmap& bitmap,
- GrSamplerState params) {
+ GrSamplerState params, SkScalar scaleAdjust[2]) {
GrBitmapTextureMaker maker(ctx, bitmap, GrBitmapTextureMaker::Cached::kYes);
- return maker.viewForParams(params);
+ return maker.viewForParams(params, scaleAdjust);
}
GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext* context, const SkBitmap& bitmap,
diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h
index 36daae1..0d97169 100644
--- a/src/gpu/SkGr.h
+++ b/src/gpu/SkGr.h
@@ -163,12 +163,15 @@
////////////////////////////////////////////////////////////////////////////////
// Texture management
-/**
- * Returns a view that wraps a texture representing the bitmap that is compatible with the
- * GrSamplerState. The texture is inserted into the cache (unless the bitmap is marked volatile)
- * and can be retrieved again via this function.
+/** Returns a view that wraps a texture representing the bitmap that is compatible with the
+ * GrSamplerState. The texture is inserted into the cache (unless the bitmap is marked volatile)
+ * and can be retrieved again via this function.
+ * The 'scaleAdjust' in/out parameter will be updated to hold any rescaling that needs to be
+ * performed on the absolute texture coordinates (e.g., if the texture is resized out to
+ * the next power of two). It can be null if the caller is sure the bitmap won't be resized.
*/
-GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, GrSamplerState);
+GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, GrSamplerState,
+ SkScalar scaleAdjust[2]);
/**
* Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index 9dfcc7c..a4abb60 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -64,7 +64,8 @@
// this call will flatten a SkImage_GpuYUV to a single texture.
virtual const GrSurfaceProxyView* view(GrRecordingContext*) const { return nullptr; }
- virtual GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const = 0;
+ virtual GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
+ SkScalar scaleAdjust[2]) const = 0;
virtual GrSurfaceProxyView refPinnedView(GrRecordingContext*, uint32_t* uniqueID) const {
return {};
}
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 7bd05ba..95002e0 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -186,8 +186,8 @@
return sContext->readPixels(dstInfo, dstPixels, dstRB, {srcX, srcY});
}
-GrSurfaceProxyView SkImage_GpuBase::refView(GrRecordingContext* context,
- GrSamplerState params) const {
+GrSurfaceProxyView SkImage_GpuBase::refView(GrRecordingContext* context, GrSamplerState params,
+ SkScalar scaleAdjust[2]) const {
if (!context || !fContext->priv().matches(context)) {
SkASSERT(0);
return {};
@@ -195,7 +195,7 @@
GrTextureAdjuster adjuster(fContext.get(), *this->view(context), this->imageInfo().colorInfo(),
this->uniqueID());
- return adjuster.viewForParams(params);
+ return adjuster.viewForParams(params, scaleAdjust);
}
GrBackendTexture SkImage_GpuBase::onGetBackendTexture(bool flushPendingGrContextIO,
diff --git a/src/image/SkImage_GpuBase.h b/src/image/SkImage_GpuBase.h
index 3f4fa52..05fc48f 100644
--- a/src/image/SkImage_GpuBase.h
+++ b/src/image/SkImage_GpuBase.h
@@ -28,7 +28,8 @@
bool onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
int srcX, int srcY, CachingHint) const override;
- GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const final;
+ GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
+ SkScalar scaleAdjust[2]) const final;
GrSurfaceProxyView refPinnedView(GrRecordingContext* context, uint32_t* uniqueID) const final {
*uniqueID = this->uniqueID();
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index 43ab458..eedd399 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -92,11 +92,13 @@
}
for (int i = 0; i < fNumViews; ++i) {
+ GrTextureProducer::CopyParams copyParams;
int mipCount = SkMipMap::ComputeLevelCount(fViews[i].proxy()->width(),
fViews[i].proxy()->height());
if (mipCount && GrGpu::IsACopyNeededForMips(fContext->priv().caps(),
fViews[i].asTextureProxy(),
- GrSamplerState::Filter::kMipMap)) {
+ GrSamplerState::Filter::kMipMap,
+ ©Params)) {
auto mippedView = GrCopyBaseMipMapToTextureProxy(context, fViews[i].asTextureProxy(),
fOrigin, fProxyColorTypes[i]);
if (!mippedView.proxy()) {
diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp
index 50b9041..81a874d 100644
--- a/src/image/SkImage_Lazy.cpp
+++ b/src/image/SkImage_Lazy.cpp
@@ -238,13 +238,14 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
-GrSurfaceProxyView SkImage_Lazy::refView(GrRecordingContext* context, GrSamplerState params) const {
+GrSurfaceProxyView SkImage_Lazy::refView(GrRecordingContext* context, GrSamplerState params,
+ SkScalar scaleAdjust[2]) const {
if (!context) {
return {};
}
GrImageTextureMaker textureMaker(context, this, kAllow_CachingHint);
- return textureMaker.viewForParams(params);
+ return textureMaker.viewForParams(params, scaleAdjust);
}
#endif
diff --git a/src/image/SkImage_Lazy.h b/src/image/SkImage_Lazy.h
index dce367b..224eaf0 100644
--- a/src/image/SkImage_Lazy.h
+++ b/src/image/SkImage_Lazy.h
@@ -42,7 +42,8 @@
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY,
CachingHint) const override;
#if SK_SUPPORT_GPU
- GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const override;
+ GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
+ SkScalar scaleAdjust[2]) const override;
sk_sp<SkCachedData> getPlanes(SkYUVASizeInfo*, SkYUVAIndex[4],
SkYUVColorSpace*, const void* planes[4]) override;
#endif
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index e1e8b4c..0764a4d 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -85,7 +85,8 @@
const SkBitmap* onPeekBitmap() const override { return &fBitmap; }
#if SK_SUPPORT_GPU
- GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const override;
+ GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
+ SkScalar scaleAdjust[2]) const override;
#endif
bool getROPixels(SkBitmap*, CachingHint) const override;
@@ -173,8 +174,8 @@
}
#if SK_SUPPORT_GPU
-GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context,
- GrSamplerState params) const {
+GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context, GrSamplerState params,
+ SkScalar scaleAdjust[2]) const {
if (!context) {
return {};
}
@@ -183,10 +184,10 @@
if (GrSurfaceProxyView view = this->refPinnedView(context, &uniqueID)) {
GrTextureAdjuster adjuster(context, std::move(view), fBitmap.info().colorInfo(),
fPinnedUniqueID);
- return adjuster.viewForParams(params);
+ return adjuster.viewForParams(params, scaleAdjust);
}
- return GrRefCachedBitmapView(context, fBitmap, params);
+ return GrRefCachedBitmapView(context, fBitmap, params, scaleAdjust);
}
#endif
@@ -209,7 +210,8 @@
} else {
SkASSERT(fPinnedCount == 0);
SkASSERT(fPinnedUniqueID == 0);
- fPinnedView = GrRefCachedBitmapView(ctx, fBitmap, GrSamplerState::Filter::kNearest);
+ fPinnedView =
+ GrRefCachedBitmapView(ctx, fBitmap, GrSamplerState::Filter::kNearest, nullptr);
if (!fPinnedView) {
return false;
}
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 9c31223..b509e0b 100755
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -213,13 +213,16 @@
fImage->width(), fImage->height(), args.fFilterQuality, *args.fViewMatrix, *lm,
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
GrSamplerState samplerState(wm, textureFilterMode);
- GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, samplerState);
+ SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
+ GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, samplerState, scaleAdjust);
if (!view) {
return nullptr;
}
SkAlphaType srcAlphaType = fImage->alphaType();
+ lmInverse.postScale(scaleAdjust[0], scaleAdjust[1]);
+
const auto& caps = *args.fContext->priv().caps();
std::unique_ptr<GrFragmentProcessor> inner;
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 1a1969a..d908365 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -970,19 +970,20 @@
sk_sp<SkImage> refImg(imageMaker(ctx));
// Any context should be able to borrow the texture at this point
- GrSurfaceProxyView view = as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest);
+ GrSurfaceProxyView view =
+ as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest, nullptr);
REPORTER_ASSERT(reporter, view);
// But once it's borrowed, no other context should be able to borrow
otherTestContext->makeCurrent();
GrSurfaceProxyView otherView =
- as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest);
+ as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest, nullptr);
REPORTER_ASSERT(reporter, !otherView);
// Original context (that's already borrowing) should be okay
testContext->makeCurrent();
GrSurfaceProxyView viewSecondRef =
- as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest);
+ as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest, nullptr);
REPORTER_ASSERT(reporter, viewSecondRef);
// Release first ref from the original context
@@ -991,7 +992,7 @@
// We released one proxy but not the other from the current borrowing context. Make sure
// a new context is still not able to borrow the texture.
otherTestContext->makeCurrent();
- otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest);
+ otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest, nullptr);
REPORTER_ASSERT(reporter, !otherView);
// Release second ref from the original context
@@ -1000,7 +1001,7 @@
// Now we should be able to borrow the texture from the other context
otherTestContext->makeCurrent();
- otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest);
+ otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest, nullptr);
REPORTER_ASSERT(reporter, otherView);
// Release everything
@@ -1041,7 +1042,8 @@
sk_sp<SkImage> image = SkImage::MakeCrossContextFromPixmap(ctx, pixmap, false);
REPORTER_ASSERT(reporter, image);
- GrSurfaceProxyView view = as_IB(image)->refView(ctx, GrSamplerState::Filter::kNearest);
+ GrSurfaceProxyView view =
+ as_IB(image)->refView(ctx, GrSamplerState::Filter::kNearest, nullptr);
REPORTER_ASSERT(reporter, view);
bool expectAlpha = kAlpha_8_SkColorType == ct;