aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-09-07 16:34:11 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-07 16:34:22 +0000
commit4df0092eac6e9bb5afc516773a0c618630193dc6 (patch)
tree7fd4a8d27fecb048c5d6e0ad00f79414696d2687
parent1e75f2a1020cde6698420d5d088c5c42e7c037ac (diff)
Revert "Remove "content" rect from GrTextureAdjuster."
This reverts commit 6e4bbbefe153495cf34ea42aa72691756e6ab40e. Reason for revert: assertion failure Original change's description: > Remove "content" rect from GrTextureAdjuster. > > Since we got rid of texture-backed bitmaps this is no longer required. > > Change-Id: Id15c745994a3d6a1489e193b5d29916fa0931264 > Reviewed-on: https://skia-review.googlesource.com/36340 > Commit-Queue: Brian Salomon <bsalomon@google.com> > Reviewed-by: Robert Phillips <robertphillips@google.com> TBR=bsalomon@google.com,robertphillips@google.com Change-Id: I2229ec05079368ff196ff351107f88062080e5ec No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/43720 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
-rw-r--r--src/gpu/GrTextureAdjuster.cpp76
-rw-r--r--src/gpu/GrTextureAdjuster.h15
-rw-r--r--src/gpu/GrTextureMaker.cpp9
-rw-r--r--src/gpu/GrTextureProducer.cpp115
-rw-r--r--src/gpu/GrTextureProducer.h3
-rw-r--r--src/gpu/SkGpuDevice.cpp6
-rw-r--r--src/gpu/SkGpuDevice_drawTexture.cpp5
-rw-r--r--src/image/SkImage_Gpu.cpp6
-rw-r--r--src/image/SkImage_Raster.cpp7
-rw-r--r--tests/DetermineDomainModeTest.cpp137
10 files changed, 282 insertions, 97 deletions
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
index 1508cb578f..546ea67b60 100644
--- a/src/gpu/GrTextureAdjuster.cpp
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -13,14 +13,22 @@
#include "SkGr.h"
GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
- SkAlphaType alphaType, uint32_t uniqueID, SkColorSpace* cs)
- : INHERITED(original->width(), original->height(),
- GrPixelConfigIsAlphaOnly(original->config()))
- , fContext(context)
- , fOriginal(std::move(original))
- , fAlphaType(alphaType)
- , fColorSpace(cs)
- , fUniqueID(uniqueID) {}
+ SkAlphaType alphaType,
+ const SkIRect& contentArea, uint32_t uniqueID,
+ SkColorSpace* cs)
+ : INHERITED(contentArea.width(), contentArea.height(),
+ GrPixelConfigIsAlphaOnly(original->config()))
+ , fContext(context)
+ , fOriginal(std::move(original))
+ , fAlphaType(alphaType)
+ , fColorSpace(cs)
+ , fUniqueID(uniqueID) {
+ SkASSERT(SkIRect::MakeWH(fOriginal->width(), fOriginal->height()).contains(contentArea));
+ if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
+ contentArea.fRight < fOriginal->width() || contentArea.fBottom < fOriginal->height()) {
+ fContentArea.set(contentArea);
+ }
+}
void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
SkColorSpace* dstColorSpace) {
@@ -46,8 +54,9 @@ sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& c
}
sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
+ const SkIRect* contentArea = this->contentAreaOrNull();
- sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), copyParams);
+ sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), contentArea, copyParams);
if (copy) {
if (key.isValid()) {
SkASSERT(copy->origin() == this->originalProxy()->origin());
@@ -60,31 +69,60 @@ sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& c
sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(
const GrSamplerParams& params,
+ SkIPoint* outOffset,
SkScalar scaleAdjust[2]) {
sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
CopyParams copyParams;
+ const SkIRect* contentArea = this->contentAreaOrNull();
if (!fContext) {
// The texture was abandoned.
return nullptr;
}
- if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, &copyParams,
- scaleAdjust)) {
+
+ if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
+ // If we generate a MIP chain for texture it will read pixel values from outside the content
+ // area.
+ copyParams.fWidth = contentArea->width();
+ copyParams.fHeight = contentArea->height();
+ copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
+ } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, &copyParams,
+ scaleAdjust)) {
+ if (outOffset) {
+ if (contentArea) {
+ outOffset->set(contentArea->fLeft, contentArea->fRight);
+ } else {
+ outOffset->set(0, 0);
+ }
+ }
return proxy;
}
sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams);
+ if (copy && outOffset) {
+ outOffset->set(0, 0);
+ }
return copy;
}
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
const SkMatrix& origTextureMatrix,
- const SkRect& constraintRect,
+ const SkRect& origConstraintRect,
FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
const GrSamplerParams::FilterMode* filterOrNullForBicubic,
SkColorSpace* dstColorSpace) {
SkMatrix textureMatrix = origTextureMatrix;
+ const SkIRect* contentArea = this->contentAreaOrNull();
+ // Convert the constraintRect to be relative to the texture rather than the content area so
+ // that both rects are in the same coordinate system.
+ SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
+ if (contentArea) {
+ SkScalar l = SkIntToScalar(contentArea->fLeft);
+ SkScalar t = SkIntToScalar(contentArea->fTop);
+ constraintRect.writable()->offset(l, t);
+ textureMatrix.postTranslate(l, t);
+ }
SkRect domain;
GrSamplerParams params;
@@ -92,19 +130,22 @@ std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
params.setFilterMode(*filterOrNullForBicubic);
}
SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
- sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, scaleAdjust));
+ sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust));
if (!proxy) {
return nullptr;
}
// If we made a copy then we only copied the contentArea, in which case the new texture is all
// content.
if (proxy.get() != this->originalProxy()) {
+ contentArea = nullptr;
textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
}
DomainMode domainMode =
- DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- proxy.get(), filterOrNullForBicubic, &domain);
+ DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ proxy.get(),
+ contentArea, filterOrNullForBicubic,
+ &domain);
if (kTightCopy_DomainMode == domainMode) {
// TODO: Copy the texture and adjust the texture matrix (both parts need to consider
// non-int constraint rect)
@@ -115,8 +156,9 @@ std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
domainMode =
- DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- proxy.get(), &kBilerp, &domain);
+ DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ proxy.get(),
+ contentArea, &kBilerp, &domain);
SkASSERT(kTightCopy_DomainMode != domainMode);
}
SkASSERT(kNoDomain_DomainMode == domainMode ||
diff --git a/src/gpu/GrTextureAdjuster.h b/src/gpu/GrTextureAdjuster.h
index 3c9d0fd3d4..fad533f30f 100644
--- a/src/gpu/GrTextureAdjuster.h
+++ b/src/gpu/GrTextureAdjuster.h
@@ -21,9 +21,10 @@
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 resulting scale
- factors used to sample the copy are returned in 'scaleAdjust'. */
- sk_sp<GrTextureProxy> refTextureProxySafeForParams(const GrSamplerParams&,
+ outOffset will be the top-left corner of the subset if a copy is not made. Otherwise,
+ the copy will be tight to the contents and outOffset will be (0, 0). 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 GrSamplerParams&, SkIPoint* outOffset,
SkScalar scaleAdjust[2]);
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
@@ -36,8 +37,8 @@ public:
// We do not ref the texture nor the colorspace, so the caller must keep them in scope while
// this Adjuster is alive.
- GrTextureAdjuster(GrContext*, sk_sp<GrTextureProxy>, SkAlphaType, uint32_t uniqueID,
- SkColorSpace*);
+ GrTextureAdjuster(GrContext*, sk_sp<GrTextureProxy>, SkAlphaType, const SkIRect& area,
+ uint32_t uniqueID, SkColorSpace*);
protected:
SkAlphaType alphaType() const override { return fAlphaType; }
@@ -48,7 +49,11 @@ protected:
GrTextureProxy* originalProxy() const { return fOriginal.get(); }
sk_sp<GrTextureProxy> originalProxyRef() const { return fOriginal; }
+ /** Returns the content area or null for the whole original texture */
+ const SkIRect* contentAreaOrNull() { return fContentArea.getMaybeNull(); }
+
private:
+ SkTLazy<SkIRect> fContentArea;
GrContext* fContext;
sk_sp<GrTextureProxy> fOriginal;
SkAlphaType fAlphaType;
diff --git a/src/gpu/GrTextureMaker.cpp b/src/gpu/GrTextureMaker.cpp
index bb30439e6e..7e257d8a78 100644
--- a/src/gpu/GrTextureMaker.cpp
+++ b/src/gpu/GrTextureMaker.cpp
@@ -59,7 +59,7 @@ sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerPa
sk_sp<GrTextureProxy> result;
if (original) {
- result = CopyOnGpu(fContext, std::move(original), copyParams);
+ result = CopyOnGpu(fContext, std::move(original), nullptr, copyParams);
} else {
result = this->generateTextureProxyForParams(copyParams, willBeMipped, dstColorSpace);
}
@@ -114,8 +114,9 @@ std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
SkRect domain;
DomainMode domainMode =
- DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- proxy.get(), fmForDetermineDomain, &domain);
+ DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ proxy.get(),
+ nullptr, fmForDetermineDomain, &domain);
SkASSERT(kTightCopy_DomainMode != domainMode);
sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
dstColorSpace);
@@ -134,5 +135,5 @@ sk_sp<GrTextureProxy> GrTextureMaker::generateTextureProxyForParams(const CopyPa
return nullptr;
}
- return CopyOnGpu(fContext, std::move(original), copyParams);
+ return CopyOnGpu(fContext, std::move(original), nullptr, copyParams);
}
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp
index f7d71fa18d..92732238e6 100644
--- a/src/gpu/GrTextureProducer.cpp
+++ b/src/gpu/GrTextureProducer.cpp
@@ -16,7 +16,9 @@
sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context,
sk_sp<GrTextureProxy> inputProxy,
+ const SkIRect* subset,
const CopyParams& copyParams) {
+ SkASSERT(!subset || !subset->isEmpty());
SkASSERT(context);
const SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
@@ -31,13 +33,23 @@ sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context,
GrPaint paint;
paint.setGammaCorrect(true);
- SkRect localRect = SkRect::MakeWH(inputProxy->width(), inputProxy->height());
+ SkRect localRect;
+ if (subset) {
+ localRect = SkRect::Make(*subset);
+ } else {
+ localRect = SkRect::MakeWH(inputProxy->width(), inputProxy->height());
+ }
bool needsDomain = false;
if (copyParams.fFilter != GrSamplerParams::kNone_FilterMode) {
bool resizing = localRect.width() != dstRect.width() ||
localRect.height() != dstRect.height();
- needsDomain = resizing && !GrResourceProvider::IsFunctionallyExact(inputProxy.get());
+
+ if (GrResourceProvider::IsFunctionallyExact(inputProxy.get())) {
+ needsDomain = subset && resizing;
+ } else {
+ needsDomain = resizing;
+ }
}
if (needsDomain) {
@@ -76,45 +88,62 @@ GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode(
FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
GrTextureProxy* proxy,
+ const SkIRect* contentRect,
const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
SkRect* domainRect) {
const SkIRect proxyBounds = SkIRect::MakeWH(proxy->width(), proxy->height());
SkASSERT(proxyBounds.contains(constraintRect));
+ // We only expect a content area rect if there is some non-content area.
+ SkASSERT(!contentRect ||
+ (!contentRect->contains(proxyBounds) &&
+ proxyBounds.contains(*contentRect) &&
+ contentRect->contains(constraintRect)));
const bool proxyIsExact = GrResourceProvider::IsFunctionallyExact(proxy);
- // We don't expect to have an image that is in an inexact proxy unless the caller was aware
- // of the potential of sampling outside of the proxy's bounds and specified a constraint rect
- // with a filter constraint.
- SkASSERT(kYes_FilterConstraint == filterConstraint || proxyIsExact);
+
// If the constraint rectangle contains the whole proxy then no need for a domain.
if (constraintRect.contains(proxyBounds) && proxyIsExact) {
return kNoDomain_DomainMode;
}
+ if (!contentRect && !proxyIsExact) {
+ contentRect = &proxyBounds;
+ }
+
bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint);
// If we can filter outside the constraint rect, and there is no non-content area of the
// proxy, and we aren't going to generate sample coords outside the constraint rect then we
// don't need a domain.
- if (!restrictFilterToRect && coordsLimitedToConstraintRect) {
+ if (!restrictFilterToRect && !contentRect && coordsLimitedToConstraintRect) {
return kNoDomain_DomainMode;
}
// Get the domain inset based on sampling mode (or bail if mipped)
+ SkScalar filterHalfWidth = 0.f;
if (filterModeOrNullForBicubic) {
switch (*filterModeOrNullForBicubic) {
case GrSamplerParams::kNone_FilterMode:
if (coordsLimitedToConstraintRect) {
return kNoDomain_DomainMode;
+ } else {
+ filterHalfWidth = 0.f;
}
break;
case GrSamplerParams::kBilerp_FilterMode:
+ filterHalfWidth = .5f;
break;
case GrSamplerParams::kMipMap_FilterMode:
- // No domain can save us with mip maps.
- return restrictFilterToRect ? kTightCopy_DomainMode : kNoDomain_DomainMode;
+ if (restrictFilterToRect || contentRect) {
+ // No domain can save us here.
+ return kTightCopy_DomainMode;
+ }
+ return kNoDomain_DomainMode;
}
+ } else {
+ // bicubic does nearest filtering internally.
+ filterHalfWidth = 1.5f;
}
// Both bilerp and bicubic use bilinear filtering and so need to be clamped to the center
@@ -126,17 +155,67 @@ GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode(
// the domain.
if (restrictFilterToRect) {
*domainRect = constraintRect.makeInset(kDomainInset, kDomainInset);
- if (domainRect->fLeft > domainRect->fRight) {
- domainRect->fLeft = domainRect->fRight =
- SkScalarAve(domainRect->fLeft, domainRect->fRight);
- }
- if (domainRect->fTop > domainRect->fBottom) {
- domainRect->fTop = domainRect->fBottom =
- SkScalarAve(domainRect->fTop, domainRect->fBottom);
+ } else if (contentRect) {
+ // If we got here then: there is a contentRect, the coords are limited to the
+ // constraint rect, and we're allowed to filter across the constraint rect boundary. So
+ // we check whether the filter would reach across the edge of the content area.
+ // We will only set the sides that are required.
+
+ domainRect->setLargest();
+ if (coordsLimitedToConstraintRect) {
+ // We may be able to use the fact that the texture coords are limited to the constraint
+ // rect in order to avoid having to add a domain.
+ bool needContentAreaConstraint = false;
+ if (contentRect->fLeft > 0 &&
+ contentRect->fLeft + filterHalfWidth > constraintRect.fLeft) {
+ domainRect->fLeft = contentRect->fLeft + kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (contentRect->fTop > 0 &&
+ contentRect->fTop + filterHalfWidth > constraintRect.fTop) {
+ domainRect->fTop = contentRect->fTop + kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if ((!proxyIsExact || contentRect->fRight < proxy->width()) &&
+ contentRect->fRight - filterHalfWidth < constraintRect.fRight) {
+ domainRect->fRight = contentRect->fRight - kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if ((!proxyIsExact || contentRect->fBottom < proxy->height()) &&
+ contentRect->fBottom - filterHalfWidth < constraintRect.fBottom) {
+ domainRect->fBottom = contentRect->fBottom - kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (!needContentAreaConstraint) {
+ return kNoDomain_DomainMode;
+ }
+ } else {
+ // Our sample coords for the texture are allowed to be outside the constraintRect so we
+ // don't consider it when computing the domain.
+ if (contentRect->fLeft > 0) {
+ domainRect->fLeft = contentRect->fLeft + kDomainInset;
+ }
+ if (contentRect->fTop > 0) {
+ domainRect->fTop = contentRect->fTop + kDomainInset;
+ }
+ if (!proxyIsExact || contentRect->fRight < proxy->width()) {
+ domainRect->fRight = contentRect->fRight - kDomainInset;
+ }
+ if (!proxyIsExact || contentRect->fBottom < proxy->height()) {
+ domainRect->fBottom = contentRect->fBottom - kDomainInset;
+ }
}
- return kDomain_DomainMode;
+ } else {
+ return kNoDomain_DomainMode;
+ }
+
+ if (domainRect->fLeft > domainRect->fRight) {
+ domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight);
+ }
+ if (domainRect->fTop > domainRect->fBottom) {
+ domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, domainRect->fBottom);
}
- return kNoDomain_DomainMode;
+ return kDomain_DomainMode;
}
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter(
diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h
index 2853a88525..ccc0dae2ee 100644
--- a/src/gpu/GrTextureProducer.h
+++ b/src/gpu/GrTextureProducer.h
@@ -119,13 +119,14 @@ protected:
};
static sk_sp<GrTextureProxy> CopyOnGpu(GrContext*, sk_sp<GrTextureProxy> inputProxy,
- const CopyParams& copyParams);
+ const SkIRect* subset, const CopyParams& copyParams);
static DomainMode DetermineDomainMode(
const SkRect& constraintRect,
FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
GrTextureProxy*,
+ const SkIRect* textureContentArea,
const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
SkRect* domainRect);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index a279c92fd1..0cf2ae5893 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1406,7 +1406,8 @@ void SkGpuDevice::drawImageNine(const SkImage* image,
ASSERT_SINGLE_OWNER
uint32_t pinnedUniqueID;
if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(&pinnedUniqueID)) {
- GrTextureAdjuster adjuster(this->context(), std::move(proxy), image->alphaType(),
+ GrTextureAdjuster adjuster(this->context(), std::move(proxy),
+ image->alphaType(), image->bounds(),
pinnedUniqueID, as_IB(image)->onImageInfo().colorSpace());
this->drawProducerNine(&adjuster, center, dst, paint);
} else {
@@ -1460,7 +1461,8 @@ void SkGpuDevice::drawImageLattice(const SkImage* image,
ASSERT_SINGLE_OWNER
uint32_t pinnedUniqueID;
if (sk_sp<GrTextureProxy> proxy = as_IB(image)->refPinnedTextureProxy(&pinnedUniqueID)) {
- GrTextureAdjuster adjuster(this->context(), std::move(proxy), image->alphaType(),
+ GrTextureAdjuster adjuster(this->context(), std::move(proxy),
+ image->alphaType(), image->bounds(),
pinnedUniqueID, as_IB(image)->onImageInfo().colorSpace());
this->drawProducerLattice(&adjuster, lattice, dst, paint);
} else {
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index 596f50445c..c861cc919e 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -145,8 +145,9 @@ void SkGpuDevice::drawPinnedTextureProxy(sk_sp<GrTextureProxy> proxy, uint32_t p
this->clip(), fRenderTargetContext.get());
return;
}
- GrTextureAdjuster adjuster(this->context(), std::move(proxy), alphaType, pinnedUniqueID,
- colorSpace);
+ auto contentRect = SkIRect::MakeWH(proxy->width(), proxy->height());
+ GrTextureAdjuster adjuster(this->context(), std::move(proxy), alphaType, contentRect,
+ pinnedUniqueID, colorSpace);
this->drawTextureProducer(&adjuster, srcRect, dstRect, constraint, viewMatrix, paint);
}
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 034f7bc742..3458075321 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -123,9 +123,9 @@ sk_sp<GrTextureProxy> SkImage_Gpu::asTextureProxyRef(GrContext* context,
*texColorSpace = this->fColorSpace;
}
- GrTextureAdjuster adjuster(fContext, fProxy, this->alphaType(), this->uniqueID(),
- this->fColorSpace.get());
- return adjuster.refTextureProxySafeForParams(params, scaleAdjust);
+ GrTextureAdjuster adjuster(fContext, fProxy, this->alphaType(), this->bounds(),
+ this->uniqueID(), this->fColorSpace.get());
+ return adjuster.refTextureProxySafeForParams(params, nullptr, 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 cb4a5b2881..5b7e83f3a7 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -186,9 +186,10 @@ sk_sp<GrTextureProxy> SkImage_Raster::asTextureProxyRef(GrContext* context,
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);
+ GrTextureAdjuster adjuster(context, fPinnedProxy,
+ fBitmap.alphaType(), fBitmap.bounds(),
+ fPinnedUniqueID, fBitmap.colorSpace());
+ return adjuster.refTextureProxySafeForParams(params, nullptr, scaleAdjust);
}
return GrRefCachedBitmapTextureProxy(context, fBitmap, params, scaleAdjust);
diff --git a/tests/DetermineDomainModeTest.cpp b/tests/DetermineDomainModeTest.cpp
index ef1a5ad09f..ee9a694f19 100644
--- a/tests/DetermineDomainModeTest.cpp
+++ b/tests/DetermineDomainModeTest.cpp
@@ -13,10 +13,11 @@
#include "GrTextureProducer.h"
#include "GrTextureProxy.h"
-// For DetermineDomainMode (in the MDB world) we have 3 rects:
+// For DetermineDomainMode (in the MDB world) we have 4 rects:
// 1) the final instantiated backing storage (i.e., the actual GrTexture's extent)
// 2) the proxy's extent, which may or may not match the GrTexture's extent
-// 3) the constraint rect, which can optionally be hard or soft
+// 3) the content rect, which can be a subset of the proxy's extent or null
+// 4) the constraint rect, which can optionally be hard or soft
// This test "fuzzes" all the combinations of these rects.
class GrTextureProducer_TestAccess {
public:
@@ -27,12 +28,14 @@ public:
GrTextureProducer::FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
GrTextureProxy* proxy,
+ const SkIRect* textureContentArea,
const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
SkRect* domainRect) {
return GrTextureProducer::DetermineDomainMode(constraintRect,
filterConstraint,
coordsLimitedToConstraintRect,
proxy,
+ textureContentArea,
filterModeOrNullForBicubic,
domainRect);
}
@@ -40,6 +43,22 @@ public:
using DomainMode = GrTextureProducer_TestAccess::DomainMode;
+#ifdef SK_DEBUG
+static bool is_irect(const SkRect& r) {
+ return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) &&
+ SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
+}
+#endif
+
+static SkIRect to_irect(const SkRect& r) {
+ SkASSERT(is_irect(r));
+ return SkIRect::MakeLTRB(SkScalarRoundToInt(r.fLeft),
+ SkScalarRoundToInt(r.fTop),
+ SkScalarRoundToInt(r.fRight),
+ SkScalarRoundToInt(r.fBottom));
+}
+
+
class RectInfo {
public:
enum Side { kLeft = 0, kTop = 1, kRight = 2, kBot = 3 };
@@ -297,6 +316,20 @@ static const SkRect* full_inset(const RectInfo& enclosing,
kInsetLeft_Flag|kInsetTop_Flag|kInsetRight_Flag|kInsetBot_Flag, name);
}
+// This is only used for content rect creation. We ensure 'result' is correct but
+// return null to indicate no content area (other than what the proxy specifies).
+static const SkRect* null_rect(const RectInfo& enclosing,
+ RectInfo* result,
+ bool isInsetHard,
+ bool areCoordsLimitedToRect,
+ float insetAmount,
+ float halfFilterWidth) {
+ static const char* name = "null";
+ generic_inset(enclosing, result, isInsetHard, areCoordsLimitedToRect,
+ insetAmount, halfFilterWidth, 0, name);
+ return nullptr;
+}
+
// Make a rect with no inset. This is only used for constraint rect creation.
static const SkRect* no_inset(const RectInfo& enclosing,
RectInfo* result,
@@ -332,50 +365,70 @@ static void proxy_test(skiatest::Reporter* reporter, GrResourceProvider* resourc
sk_sp<GrTextureProxy> proxy = create_proxy(resourceProvider, isPowerOfTwoSized,
isExact, &outermost);
SkASSERT(outermost.isHardOrBadAllAround());
- for (auto isConstraintRectHard : { true, false }) {
- if (!isConstraintRectHard && !isExact) {
- // GrTextureProducer expects that texture inexactness is expressed as a
- // constraint rect and asserts if not. This skips a case that never happens
- // through the public API.
- continue;
+
+ for (auto contentRectMaker : { left_only, top_only, right_only,
+ bot_only, full_inset, null_rect}) {
+ RectInfo contentRectStorage;
+ const SkRect* contentRect = (*contentRectMaker)(outermost,
+ &contentRectStorage,
+ true, false, 5.0f, -1.0f);
+ if (contentRect) {
+ // We only have content rects if they actually reduce the extent of the content
+ SkASSERT(!contentRect->contains(outermost.rect()));
+ SkASSERT(outermost.rect().contains(*contentRect));
+ SkASSERT(is_irect(*contentRect));
}
- for (auto areCoordsLimitedToConstraintRect : { true, false }) {
- for (int filterMode = 0; filterMode < 4; ++filterMode) {
- for (auto constraintRectMaker : { left_only, top_only, right_only,
- bot_only, full_inset, no_inset }) {
- for (auto insetAmt : { 0.25f, 0.75f, 1.25f, 1.75f, 5.0f }) {
- RectInfo constraintRectStorage;
- const SkRect* constraintRect = (*constraintRectMaker)(
- outermost,
- &constraintRectStorage,
- isConstraintRectHard,
- areCoordsLimitedToConstraintRect,
- insetAmt,
- gHalfFilterWidth[filterMode]);
- SkASSERT(constraintRect); // always need one of these
- SkASSERT(outermost.rect().contains(*constraintRect));
-
- actualMode = GrTextureProducer_TestAccess::DetermineDomainMode(
- *constraintRect,
- isConstraintRectHard
- ? GrTextureProducer::kYes_FilterConstraint
- : GrTextureProducer::kNo_FilterConstraint,
- areCoordsLimitedToConstraintRect,
- proxy.get(),
- gModePtrs[filterMode],
- &actualDomainRect);
-
- expectedMode = DomainMode::kNoDomain_DomainMode;
- if (constraintRectStorage.hasABad()) {
- if (3 == filterMode) {
- expectedMode = DomainMode::kTightCopy_DomainMode;
+ SkASSERT(contentRectStorage.isHardOrBadAllAround());
+
+ for (auto isConstraintRectHard : { true, false }) {
+ for (auto areCoordsLimitedToConstraintRect : { true, false }) {
+ for (int filterMode = 0; filterMode < 4; ++filterMode) {
+ for (auto constraintRectMaker : { left_only, top_only, right_only,
+ bot_only, full_inset, no_inset }) {
+ for (auto insetAmt : { 0.25f, 0.75f, 1.25f, 1.75f, 5.0f }) {
+ RectInfo constraintRectStorage;
+ const SkRect* constraintRect = (*constraintRectMaker)(
+ contentRect ? contentRectStorage : outermost,
+ &constraintRectStorage,
+ isConstraintRectHard,
+ areCoordsLimitedToConstraintRect,
+ insetAmt,
+ gHalfFilterWidth[filterMode]);
+ SkASSERT(constraintRect); // always need one of these
+ if (contentRect) {
+ SkASSERT(contentRect->contains(*constraintRect));
} else {
- expectedMode = DomainMode::kDomain_DomainMode;
+ SkASSERT(outermost.rect().contains(*constraintRect));
}
- }
- REPORTER_ASSERT(reporter, expectedMode == actualMode);
- // TODO: add a check that the returned domain rect is correct
+ SkIRect contentIRect;
+ if (contentRect) {
+ contentIRect = to_irect(*contentRect);
+ }
+
+ actualMode = GrTextureProducer_TestAccess::DetermineDomainMode(
+ *constraintRect,
+ isConstraintRectHard
+ ? GrTextureProducer::kYes_FilterConstraint
+ : GrTextureProducer::kNo_FilterConstraint,
+ areCoordsLimitedToConstraintRect,
+ proxy.get(),
+ contentRect ? &contentIRect : nullptr,
+ gModePtrs[filterMode],
+ &actualDomainRect);
+
+ expectedMode = DomainMode::kNoDomain_DomainMode;
+ if (constraintRectStorage.hasABad()) {
+ if (3 == filterMode) {
+ expectedMode = DomainMode::kTightCopy_DomainMode;
+ } else {
+ expectedMode = DomainMode::kDomain_DomainMode;
+ }
+ }
+
+ REPORTER_ASSERT(reporter, expectedMode == actualMode);
+ // TODO: add a check that the returned domain rect is correct
+ }
}
}
}