Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(480)

Unified Diff: src/gpu/GrTextureParamsAdjuster.cpp

Issue 1424313010: Separate out natively-texture image/bmp draws from cached-as-texture image/bmp draws (Closed) Base URL: https://skia.googlesource.com/skia.git@const
Patch Set: update Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrTextureParamsAdjuster.h ('k') | src/gpu/SkGpuDevice.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrTextureParamsAdjuster.cpp
diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp
index 579cf96ef36d30823a70b491cc0015e6813be116..b98a126971de0836d666226a184179d50588632c 100644
--- a/src/gpu/GrTextureParamsAdjuster.cpp
+++ b/src/gpu/GrTextureParamsAdjuster.cpp
@@ -19,6 +19,7 @@
#include "SkCanvas.h"
#include "SkGr.h"
#include "SkGrPriv.h"
+#include "effects/GrBicubicEffect.h"
#include "effects/GrTextureDomain.h"
typedef GrTextureProducer::CopyParams CopyParams;
@@ -131,7 +132,7 @@ GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrTextureParams& par
GrTexture* texture = this->originalTexture();
GrContext* context = texture->getContext();
CopyParams copyParams;
- const SkIRect* contentArea = this->contentArea();
+ const SkIRect* contentArea = this->contentAreaOrNull();
if (contentArea && GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
// If we generate a MIP chain for texture it will read pixel values from outside the content
@@ -171,6 +172,211 @@ GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrTextureParams& par
return result;
}
+enum DomainMode {
+ kNoDomain_DomainMode,
+ kDomain_DomainMode,
+ kTightCopy_DomainMode
+};
+
+/** Determines whether a texture domain is necessary and if so what domain to use. There are two
+ * rectangles to consider:
+ * - The first is the content area specified by the texture adjuster. We can *never* allow
+ * filtering to cause bleed of pixels outside this rectangle.
+ * - The second rectangle is the constraint rectangle, which is known to be contained by the
+ * content area. The filterConstraint specifies whether we are allowed to bleed across this
+ * rect.
+ *
+ * We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
+ * and whether the coords generated by the draw would all fall within the constraint rect. If the
+ * latter is true we only need to consider whether the filter would extend beyond the rects.
+ */
+static DomainMode determine_domain_mode(
+ const SkRect& constraintRect,
+ GrTextureAdjuster::FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ int texW, int texH,
+ const SkIRect* textureContentArea,
+ const GrTextureParams::FilterMode* filterModeOrNullForBicubic,
+ SkRect* domainRect) {
+
+ SkASSERT(SkRect::MakeIWH(texW, texH).contains(constraintRect));
+ // We only expect a content area rect if there is some non-content area.
+ SkASSERT(!textureContentArea ||
+ (!textureContentArea->contains(SkIRect::MakeWH(texW, texH)) &&
+ SkRect::Make(*textureContentArea).contains(constraintRect)));
+
+ SkRect textureBounds = SkRect::MakeIWH(texW, texH);
+ // If the src rectangle contains the whole texture then no need for a domain.
+ if (constraintRect.contains(textureBounds)) {
+ return kNoDomain_DomainMode;
+ }
+
+ bool restrictFilterToRect = (filterConstraint == GrTextureAdjuster::kYes_FilterConstraint);
+
+ // If we can filter outside the constraint rect, and there is no non-content area of the
+ // texture, and we aren't going to generate sample coords outside the constraint rect then we
+ // don't need a domain.
+ if (!restrictFilterToRect && !textureContentArea && 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 GrTextureParams::kNone_FilterMode:
+ if (coordsLimitedToConstraintRect) {
+ return kNoDomain_DomainMode;
+ } else {
+ filterHalfWidth = 0.f;
+ }
+ break;
+ case GrTextureParams::kBilerp_FilterMode:
+ filterHalfWidth = .5f;
+ break;
+ case GrTextureParams::kMipMap_FilterMode:
+ // No domain can save use here.
+ return kTightCopy_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
+ // of the edge texel. Pinning to the texel center has no impact on nearest mode and MIP-maps
+
+ static const SkScalar kDomainInset = 0.5f;
+ // Figure out the limits of pixels we're allowed to sample from.
+ // Unless we know the amount of outset and the texture matrix we have to conservatively enforce
+ // the domain.
+ if (restrictFilterToRect) {
+ domainRect->fLeft = constraintRect.fLeft + kDomainInset;
+ domainRect->fTop = constraintRect.fTop + kDomainInset;
+ domainRect->fRight = constraintRect.fRight - kDomainInset;
+ domainRect->fBottom = constraintRect.fBottom - kDomainInset;
+ } else if (textureContentArea) {
+ // If we got here then: there is a textureContentArea, 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 (textureContentArea->fLeft > 0 &&
+ textureContentArea->fLeft + filterHalfWidth > constraintRect.fLeft) {
+ domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (textureContentArea->fTop > 0 &&
+ textureContentArea->fTop + filterHalfWidth > constraintRect.fTop) {
+ domainRect->fTop = textureContentArea->fTop + kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (textureContentArea->fRight < texW &&
+ textureContentArea->fRight - filterHalfWidth < constraintRect.fRight) {
+ domainRect->fRight = textureContentArea->fRight - kDomainInset;
+ needContentAreaConstraint = true;
+ }
+ if (textureContentArea->fBottom < texH &&
+ textureContentArea->fBottom - filterHalfWidth < constraintRect.fBottom) {
+ domainRect->fBottom = textureContentArea->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 (textureContentArea->fLeft != 0) {
+ domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
+ }
+ if (textureContentArea->fTop != 0) {
+ domainRect->fTop = textureContentArea->fTop + kDomainInset;
+ }
+ if (textureContentArea->fRight != texW) {
+ domainRect->fRight = textureContentArea->fRight - kDomainInset;
+ }
+ if (textureContentArea->fBottom != texH) {
+ domainRect->fBottom = textureContentArea->fBottom - kDomainInset;
+ }
+ }
+ } 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);
+ }
+ domainRect->fLeft /= texW;
+ domainRect->fTop /= texH;
+ domainRect->fRight /= texW;
+ domainRect->fBottom /= texH;
+ return kDomain_DomainMode;
+}
+
+const GrFragmentProcessor* GrTextureAdjuster::createFragmentProcessor(
+ const SkMatrix& textureMatrix,
+ const SkRect& constraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrTextureParams::FilterMode* filterOrNullForBicubic) {
+
+ const SkIRect* contentArea = this->contentAreaOrNull();
+
+ SkRect domain;
+ GrTexture* texture = this->originalTexture();
+ DomainMode domainMode =
+ determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(),
+ 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)
+ // For now: treat as bilerp and ignore what goes on above level 0.
+
+ // We only expect MIP maps to require a tight copy.
+ SkASSERT(filterOrNullForBicubic &&
+ GrTextureParams::kMipMap_FilterMode == *filterOrNullForBicubic);
+ static const GrTextureParams::FilterMode kBilerp = GrTextureParams::kBilerp_FilterMode;
+ domainMode =
+ determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(),
+ contentArea, &kBilerp, &domain);
+ SkASSERT(kTightCopy_DomainMode != domainMode);
+ filterOrNullForBicubic = &kBilerp;
+ }
+ SkASSERT(kNoDomain_DomainMode == domainMode ||
+ (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
+ if (filterOrNullForBicubic) {
+ if (kDomain_DomainMode == domainMode) {
+ SkASSERT(*filterOrNullForBicubic != GrTextureParams::kMipMap_FilterMode);
+ return GrTextureDomainEffect::Create(texture, textureMatrix, domain,
+ GrTextureDomain::kClamp_Mode,
+ *filterOrNullForBicubic);
+ } else {
+ GrTextureParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
+ return GrSimpleTextureEffect::Create(texture, textureMatrix, params);
+ }
+ } else {
+ if (kDomain_DomainMode == domainMode) {
+ return GrBicubicEffect::Create(texture, textureMatrix, domain);
+ } else {
+ static const SkShader::TileMode kClampClamp[] =
+ { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
+ return GrBicubicEffect::Create(texture, textureMatrix, kClampClamp);
+ }
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////
GrTexture* GrTextureMaker::refTextureForParams(GrContext* ctx, const GrTextureParams& params) {
« no previous file with comments | « src/gpu/GrTextureParamsAdjuster.h ('k') | src/gpu/SkGpuDevice.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698