}
GrTextureAdjuster::GrTextureAdjuster(GrTexture* original, const SkIRect& contentArea)
- : fOriginal(original) {
+ : INHERITED(contentArea.width(), contentArea.height())
+ , fOriginal(original) {
+ SkASSERT(SkIRect::MakeWH(original->width(), original->height()).contains(contentArea));
if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
fContentArea.set(contentArea);
}
const GrFragmentProcessor* GrTextureAdjuster::createFragmentProcessor(
- const SkMatrix& textureMatrix,
- const SkRect& constraintRect,
+ const SkMatrix& origTextureMatrix,
+ const SkRect& origConstraintRect,
FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
const GrTextureParams::FilterMode* filterOrNullForBicubic) {
+ 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;
GrTexture* texture = this->originalTexture();
DomainMode domainMode =
- determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
texture->width(), texture->height(),
contentArea, filterOrNullForBicubic,
&domain);
GrTextureParams::kMipMap_FilterMode == *filterOrNullForBicubic);
static const GrTextureParams::FilterMode kBilerp = GrTextureParams::kBilerp_FilterMode;
domainMode =
- determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
texture->width(), texture->height(),
contentArea, &kBilerp, &domain);
SkASSERT(kTightCopy_DomainMode != domainMode);
}
SkASSERT(kNoDomain_DomainMode == domainMode ||
(domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
+ textureMatrix.postIDiv(texture->width(), texture->height());
if (filterOrNullForBicubic) {
if (kDomain_DomainMode == domainMode) {
return GrTextureDomainEffect::Create(texture, textureMatrix, domain,
#include "GrTextureParams.h"
#include "GrResourceKey.h"
#include "GrTexture.h"
+#include "SkFunction.h"
#include "SkTLazy.h"
class GrContext;
virtual ~GrTextureProducer() {}
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+
protected:
+ GrTextureProducer(int width, int height) : fWidth(width), fHeight(height) {}
+
/** Helper for creating a key for a copy from an original key. */
static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
const CopyParams& copyParams,
*/
virtual void didCacheCopy(const GrUniqueKey& copyKey) = 0;
+private:
+ const int fWidth;
+ const int fHeight;
+
typedef SkNoncopyable INHERITED;
};
* It attempts to avoids making a copy of the texture and avoid using a texture domain unless
* necessary.
*
- * @param textureMatrix Matrix to transform local coords by to compute
- * texture coords.
- * @param constraintRect Subrect of content area to be rendered. Must be
- * clipped to the content area already.
+ * @param textureMatrix Matrix to apply to local coordinates to compute
+ * texel coordinates. The post-transformed coordinates
+ * should be in texels (relative to this->width() and
+ * this->height()) and not be normalized.
+ * @param constraintRect Subrect of content area to be rendered. The
+ * constraint rect is relative to the content area.
* @param filterConstriant Indicates whether filtering is limited to
* constraintRect.
* @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
bool coordsLimitedToConstraintRect,
const GrTextureParams::FilterMode* filterOrNullForBicubic);
- GrTexture* originalTexture() const { return fOriginal; }
-
- void getContentArea(SkIRect* contentArea) const {
- if (fContentArea.isValid()) {
- *contentArea = *fContentArea.get();
- } else {
- *contentArea = SkIRect::MakeWH(fOriginal->width(), fOriginal->height());
- }
- }
-
protected:
/** The whole texture is content. */
- explicit GrTextureAdjuster(GrTexture* original): fOriginal(original) {}
+ explicit GrTextureAdjuster(GrTexture* original)
+ : INHERITED(original->width(), original->height())
+ , fOriginal(original) {}
GrTextureAdjuster(GrTexture* original, const SkIRect& contentArea);
+ GrTexture* originalTexture() const { return fOriginal; }
+
/** Returns the content area or null for the whole original texture */
const SkIRect* contentAreaOrNull() { return fContentArea.getMaybeNull(); }
*/
class GrTextureMaker : public GrTextureProducer {
public:
-
- GrTextureMaker(int width, int height) : fWidth(width), fHeight(height) {}
-
- int width() const { return fWidth; }
- int height() const { return fHeight; }
-
/** Returns a texture that is safe for use with the params. If the size of the returned texture
does not match width()/height() then the contents of the original must be scaled to fit
the texture. */
GrTexture* refTextureForParams(GrContext*, const GrTextureParams&);
protected:
+ GrTextureMaker(int width, int height) : INHERITED(width, height) {}
+
/**
* Return the maker's "original" texture. It is the responsibility of the maker
* to make this efficient ... if the texture is being generated, the maker must handle
virtual GrTexture* generateTextureForParams(GrContext*, const CopyParams&);
private:
- const int fWidth;
- const int fHeight;
-
typedef GrTextureProducer INHERITED;
};
// the matrix that maps the src rect to the dst rect.
SkRect clippedSrcRect;
SkRect clippedDstRect;
- SkIRect contentIBounds;
- adjuster->getContentArea(&contentIBounds);
- const SkRect contentBounds = SkRect::Make(contentIBounds);
+ const SkRect srcBounds = SkRect::MakeIWH(adjuster->width(), adjuster->height());
SkMatrix srcToDstMatrix;
if (srcRect) {
if (!dstRect) {
- dstRect = &contentBounds;
+ dstRect = &srcBounds;
}
- if (!contentBounds.contains(*srcRect)) {
+ if (!srcBounds.contains(*srcRect)) {
clippedSrcRect = *srcRect;
- if (!clippedSrcRect.intersect(contentBounds)) {
+ if (!clippedSrcRect.intersect(srcBounds)) {
return;
}
if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFill_ScaleToFit)) {
}
}
} else {
- clippedSrcRect = contentBounds;
+ clippedSrcRect = srcBounds;
if (dstRect) {
clippedDstRect = *dstRect;
- if (!srcToDstMatrix.setRectToRect(contentBounds, *dstRect,
- SkMatrix::kFill_ScaleToFit)) {
+ if (!srcToDstMatrix.setRectToRect(srcBounds, *dstRect, SkMatrix::kFill_ScaleToFit)) {
return;
}
} else {
- clippedDstRect = contentBounds;
+ clippedDstRect = srcBounds;
srcToDstMatrix.reset();
}
}
// by not baking anything about the srcRect, dstRect, or viewMatrix, into the texture FP. In
// the future this should be an opaque optimization enabled by the combination of batch/GP and
// FP.
- SkMatrix textureFPMatrix;
const SkMaskFilter* mf = paint.getMaskFilter();
- GrTexture* texture = adjuster->originalTexture();
// The shader expects proper local coords, so we can't replace local coords with texture coords
// if the shader will be used. If we have a mask filter we will change the underlying geometry
// that is rendered.
bool canUseTextureCoordsAsLocalCoords = !use_shader(alphaTexture, paint) && !mf;
- if (canUseTextureCoordsAsLocalCoords) {
- textureFPMatrix.setIDiv(texture->width(), texture->height());
- } else {
- if (!srcToDstMatrix.invert(&textureFPMatrix)) {
- return;
- }
- textureFPMatrix.postIDiv(texture->width(), texture->height());
- }
bool doBicubic;
GrTextureParams::FilterMode fm =
// This is conservative as a mask filter does not have to expand the bounds rendered.
bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf;
+ const SkMatrix* textureMatrix;
+ SkMatrix tempMatrix;
+ if (canUseTextureCoordsAsLocalCoords) {
+ textureMatrix = &SkMatrix::I();
+ } else {
+ if (!srcToDstMatrix.invert(&tempMatrix)) {
+ return;
+ }
+ textureMatrix = &tempMatrix;
+ }
SkAutoTUnref<const GrFragmentProcessor> fp(adjuster->createFragmentProcessor(
- textureFPMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect, filterMode));
+ *textureMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect, filterMode));
if (!fp) {
return;
}