Revert "Remove "content" rect from GrTextureAdjuster."

This reverts commit 6e4bbbefe1.

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>
This commit is contained in:
Brian Salomon 2017-09-07 16:34:11 +00:00 committed by Skia Commit-Bot
parent 1e75f2a102
commit 4df0092eac
10 changed files with 281 additions and 96 deletions

View File

@ -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 ||

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
} 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;
}
}
if (domainRect->fTop > domainRect->fBottom) {
domainRect->fTop = domainRect->fBottom =
SkScalarAve(domainRect->fTop, domainRect->fBottom);
}
return kDomain_DomainMode;
} else {
return kNoDomain_DomainMode;
}
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 kDomain_DomainMode;
}
std::unique_ptr<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter(

View File

@ -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);

View File

@ -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 {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);

View File

@ -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));
SkASSERT(contentRectStorage.isHardOrBadAllAround());
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;
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
}
}
}
}