Add generic texture op factory.
This adds a new factory for GrTextureOp that generalizes the current
Make() and MakeQuad(). A following CL will remove those calls.
This also moves the texture-op emulation with GrFillRectOp into this
factory call. I found this to make more sense, both because it makes
op creation callsites simpler (drawTexturedQuad, drawTexture, and
drawTextureSet don't have to check the blend mode anymore). Additionally
the logic for matching the texture op shading behavior to a GrPaint
now lives inside GrTextureOp.
To allow for this, the to-be-removed existing factories have had the
blend mode added to their arguments as well.
Change-Id: Icda346cd203ae8caa7f5ed762ed4e0a214084dda
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223924
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index d1b0c37..306ce5e 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -881,31 +881,6 @@
fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
}
-// Creates a paint for GrFillRectOp that matches behavior of GrTextureOp
-static void draw_texture_to_grpaint(sk_sp<GrTextureProxy> proxy, const SkRect* domain,
- GrSamplerState::Filter filter, SkBlendMode mode,
- const SkPMColor4f& color, sk_sp<GrColorSpaceXform> csXform,
- GrPaint* paint) {
- paint->setColor4f(color);
- paint->setXPFactory(SkBlendMode_AsXPFactory(mode));
-
- std::unique_ptr<GrFragmentProcessor> fp;
- if (domain) {
- SkRect correctedDomain = *domain;
- if (filter == GrSamplerState::Filter::kBilerp) {
- // Inset by 1/2 pixel, which GrTextureOp and GrTextureAdjuster handle automatically
- correctedDomain.inset(0.5f, 0.5f);
- }
- fp = GrTextureDomainEffect::Make(std::move(proxy), SkMatrix::I(), correctedDomain,
- GrTextureDomain::kClamp_Mode, filter);
- } else {
- fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I(), filter);
- }
-
- fp = GrColorSpaceXformEffect::Make(std::move(fp), csXform);
- paint->addColorFragmentProcessor(std::move(fp));
-}
-
void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
GrSamplerState::Filter filter, SkBlendMode mode,
const SkPMColor4f& color, const SkRect& srcRect,
@@ -931,29 +906,9 @@
}
AutoCheckFlush acf(this->drawingManager());
-
- std::unique_ptr<GrDrawOp> op;
- if (mode != SkBlendMode::kSrcOver) {
- // Emulation mode with GrPaint and GrFillRectOp
- if (filter != GrSamplerState::Filter::kNearest &&
- !GrTextureOp::GetFilterHasEffect(viewMatrix, clippedSrcRect, clippedDstRect)) {
- filter = GrSamplerState::Filter::kNearest;
- }
-
- GrPaint paint;
- draw_texture_to_grpaint(std::move(proxy),
- constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
- filter, mode, color, std::move(textureColorSpaceXform), &paint);
- op = GrFillRectOp::Make(fContext, std::move(paint), aaType, aaFlags,
- GrQuad::MakeFromRect(clippedDstRect, viewMatrix),
- GrQuad(clippedSrcRect));
- } else {
- // Can use a lighter weight op that can chain across proxies
- op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
- clippedDstRect, aaType, aaFlags, constraint, viewMatrix,
- std::move(textureColorSpaceXform));
- }
-
+ auto op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
+ clippedDstRect, aaType, aaFlags, constraint, viewMatrix,
+ std::move(textureColorSpaceXform), mode);
this->addDrawOp(clip, std::move(op));
}
@@ -977,22 +932,8 @@
// Unlike drawTexture(), don't bother cropping or optimizing the filter type since we're
// sampling an arbitrary quad of the texture.
AutoCheckFlush acf(this->drawingManager());
- std::unique_ptr<GrDrawOp> op;
- if (mode != SkBlendMode::kSrcOver) {
- // Emulation mode, but don't bother converting to kNearest filter since it's an arbitrary
- // quad that is being drawn, which makes the tests too expensive here
- GrPaint paint;
- draw_texture_to_grpaint(
- std::move(proxy), domain, filter, mode, color, std::move(texXform), &paint);
- op = GrFillRectOp::Make(fContext, std::move(paint), aaType, aaFlags,
- GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
- GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()));
- } else {
- // Use lighter weight GrTextureOp
- op = GrTextureOp::MakeQuad(fContext, std::move(proxy), filter, color, srcQuad, dstQuad,
- aaType, aaFlags, domain, viewMatrix, std::move(texXform));
- }
-
+ auto op = GrTextureOp::MakeQuad(fContext, std::move(proxy), filter, color, srcQuad, dstQuad,
+ aaType, aaFlags, domain, viewMatrix, std::move(texXform), mode);
this->addDrawOp(clip, std::move(op));
}
@@ -1008,7 +949,8 @@
if (mode != SkBlendMode::kSrcOver ||
!fContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
- // Draw one at a time with GrFillRectOp and a GrPaint that emulates what GrTextureOp does
+ // Draw one at a time since the bulk API doesn't support non src-over blending, or the
+ // backend can't support the bulk geometry processor yet.
SkMatrix ctm;
for (int i = 0; i < cnt; ++i) {
float alpha = set[i].fAlpha;
diff --git a/src/gpu/geometry/GrQuad.cpp b/src/gpu/geometry/GrQuad.cpp
index 78f4e3b..3df11ca 100644
--- a/src/gpu/geometry/GrQuad.cpp
+++ b/src/gpu/geometry/GrQuad.cpp
@@ -132,3 +132,14 @@
// If rect, ws must all be 1s so no need to divide
return aa_affects_rect(fX[0], fY[0], fX[3], fY[3]);
}
+
+bool GrQuad::asRect(SkRect* rect) const {
+ if (this->quadType() != Type::kAxisAligned) {
+ return false;
+ }
+
+ *rect = this->bounds();
+ // v0 at the geometric top-left is unique amongst axis-aligned vertex orders
+ // (90, 180, 270 rotations or axis flips all move v0).
+ return fX[0] == rect->fLeft && fY[0] == rect->fTop;
+}
diff --git a/src/gpu/geometry/GrQuad.h b/src/gpu/geometry/GrQuad.h
index 361c9a3..9131ff6 100644
--- a/src/gpu/geometry/GrQuad.h
+++ b/src/gpu/geometry/GrQuad.h
@@ -129,6 +129,11 @@
// True if anti-aliasing affects this quad. Only valid when quadType == kAxisAligned
bool aaHasEffectOnRect() const;
+ // True if this quad is axis-aligned and still has its top-left corner at v0. Equivalently,
+ // quad == GrQuad(quad->bounds()). Axis-aligned quads with flips and rotations may exactly
+ // fill their bounds, but their vertex order will not match TL BL TR BR anymore.
+ bool asRect(SkRect* rect) const;
+
// The non-const pointers are provided to support modifying a GrQuad in-place, but care must be
// taken to keep its quad type aligned with the geometric nature of the new coordinates. This is
// no different than using the constructors that accept a quad type.
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 127cb45..daede5f 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -11,6 +11,7 @@
#include "include/core/SkPoint3.h"
#include "include/gpu/GrTexture.h"
#include "include/private/GrRecordingContext.h"
+#include "include/private/SkFloatingPoint.h"
#include "include/private/SkTo.h"
#include "src/core/SkMathPriv.h"
#include "src/core/SkMatrixPriv.h"
@@ -29,10 +30,12 @@
#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/SkGr.h"
+#include "src/gpu/effects/GrTextureDomain.h"
#include "src/gpu/geometry/GrQuad.h"
#include "src/gpu/geometry/GrQuadBuffer.h"
#include "src/gpu/geometry/GrQuadUtils.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
+#include "src/gpu/ops/GrFillRectOp.h"
#include "src/gpu/ops/GrMeshDrawOp.h"
#include "src/gpu/ops/GrQuadPerEdgeAA.h"
@@ -42,6 +45,50 @@
using VertexSpec = GrQuadPerEdgeAA::VertexSpec;
using ColorType = GrQuadPerEdgeAA::ColorType;
+// Extracts lengths of vertical and horizontal edges of axis-aligned quad. "width" is the edge
+// between v0 and v2 (or v1 and v3), "height" is the edge between v0 and v1 (or v2 and v3).
+static SkSize axis_aligned_quad_size(const GrQuad& quad) {
+ SkASSERT(quad.quadType() == GrQuad::Type::kAxisAligned);
+ // Simplification of regular edge length equation, since it's axis aligned and can avoid sqrt
+ float dw = sk_float_abs(quad.x(2) - quad.x(0)) + sk_float_abs(quad.y(2) - quad.y(0));
+ float dh = sk_float_abs(quad.x(1) - quad.x(0)) + sk_float_abs(quad.y(1) - quad.y(0));
+ return {dw, dh};
+}
+
+static bool filter_has_effect(const GrQuad& srcQuad, const GrQuad& dstQuad) {
+ // If not axis-aligned in src or dst, then always say it has an effect
+ if (srcQuad.quadType() != GrQuad::Type::kAxisAligned ||
+ dstQuad.quadType() != GrQuad::Type::kAxisAligned) {
+ return true;
+ }
+
+ SkRect srcRect;
+ SkRect dstRect;
+ if (srcQuad.asRect(&srcRect) && dstQuad.asRect(&dstRect)) {
+ // Disable filtering when there is no scaling (width and height are the same), and the
+ // top-left corners have the same fraction (so src and dst snap to the pixel grid
+ // identically).
+ SkASSERT(srcRect.isSorted());
+ return srcRect.width() != dstRect.width() || srcRect.height() != dstRect.height() ||
+ SkScalarFraction(srcRect.fLeft) != SkScalarFraction(dstRect.fLeft) ||
+ SkScalarFraction(srcRect.fTop) != SkScalarFraction(dstRect.fTop);
+ } else {
+ // Although the quads are axis-aligned, the local coordinate system is transformed such
+ // that fractionally-aligned sample centers will not align with the device coordinate system
+ // So disable filtering when edges are the same length and both srcQuad and dstQuad
+ // 0th vertex is integer aligned.
+ if (SkScalarIsInt(srcQuad.x(0)) && SkScalarIsInt(srcQuad.y(0)) &&
+ SkScalarIsInt(dstQuad.x(0)) && SkScalarIsInt(dstQuad.y(0))) {
+ // Extract edge lengths
+ SkSize srcSize = axis_aligned_quad_size(srcQuad);
+ SkSize dstSize = axis_aligned_quad_size(dstQuad);
+ return srcSize.fWidth != dstSize.fWidth || srcSize.fHeight != dstSize.fHeight;
+ } else {
+ return true;
+ }
+ }
+}
+
// if normalizing the domain then pass 1/width, 1/height, 1 for iw, ih, h. Otherwise pass
// 1, 1, and height.
static void compute_domain(Domain domain, GrSamplerState::Filter filter, GrSurfaceOrigin origin,
@@ -96,52 +143,18 @@
public:
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
sk_sp<GrTextureProxy> proxy,
+ sk_sp<GrColorSpaceXform> textureXform,
GrSamplerState::Filter filter,
const SkPMColor4f& color,
- const SkRect& srcRect,
- const SkRect& dstRect,
GrAAType aaType,
GrQuadAAFlags aaFlags,
- SkCanvas::SrcRectConstraint constraint,
- const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
- GrQuad dstQuad = GrQuad::MakeFromRect(dstRect, viewMatrix);
- GrQuad srcQuad = GrQuad(srcRect);
- const SkRect* domain =
- constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr;
- if (dstQuad.quadType() == GrQuad::Type::kAxisAligned) {
- // Disable filtering if possible (note AA optimizations for rects are automatically
- // handled above in GrResolveAATypeForQuad).
- if (filter != GrSamplerState::Filter::kNearest &&
- !GrTextureOp::GetFilterHasEffect(viewMatrix, srcRect, dstRect)) {
- filter = GrSamplerState::Filter::kNearest;
- }
- }
-
+ const GrQuad& deviceQuad,
+ const GrQuad& localQuad,
+ const SkRect* domain) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<TextureOp>(
- std::move(proxy), filter, color, dstQuad, srcQuad, domain,
- aaType, aaFlags, std::move(textureColorSpaceXform));
- }
- static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
- sk_sp<GrTextureProxy> proxy,
- GrSamplerState::Filter filter,
- const SkPMColor4f& color,
- const SkPoint srcQuad[4],
- const SkPoint dstQuad[4],
- GrAAType aaType,
- GrQuadAAFlags aaFlags,
- const SkRect* domain,
- const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
- GrQuad grDstQuad = GrQuad::MakeFromSkQuad(dstQuad, viewMatrix);
- GrQuad grSrcQuad = GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I());
-
- GrOpMemoryPool* pool = context->priv().opMemoryPool();
- // Pass domain as srcRect if provided, but send srcQuad as a GrQuad for local coords
- return pool->allocate<TextureOp>(
- std::move(proxy), filter, color, grDstQuad, grSrcQuad, domain,
- aaType, aaFlags, std::move(textureColorSpaceXform));
+ std::move(proxy), std::move(textureXform), filter, color, aaType, aaFlags,
+ deviceQuad, localQuad, domain);
}
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
const GrRenderTargetContext::TextureSetEntry set[],
@@ -250,10 +263,10 @@
// dstQuad should be the geometry transformed by the view matrix. If domainRect
// is not null it will be used to apply the strict src rect constraint.
- TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, const SkPMColor4f& color,
- const GrQuad& dstQuad, const GrQuad& srcQuad, const SkRect* domainRect,
+ TextureOp(sk_sp<GrTextureProxy> proxy, sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ GrSamplerState::Filter filter, const SkPMColor4f& color,
GrAAType aaType, GrQuadAAFlags aaFlags,
- sk_sp<GrColorSpaceXform> textureColorSpaceXform)
+ const GrQuad& dstQuad, const GrQuad& srcQuad, const SkRect* domainRect)
: INHERITED(ClassID())
, fQuads(1, true /* includes locals */)
, fTextureColorSpaceXform(std::move(textureColorSpaceXform))
@@ -321,6 +334,10 @@
srcQuad = GrQuad(set[p].fSrcRect);
}
+ if (!mustFilter && this->filter() != GrSamplerState::Filter::kNearest) {
+ mustFilter = filter_has_effect(srcQuad, quad);
+ }
+
bounds.joinPossiblyEmptyRect(quad.bounds());
GrQuadAAFlags aaFlags;
// Don't update the overall aaType, might be inappropriate for some of the quads
@@ -331,10 +348,6 @@
if (overallAAType == GrAAType::kNone && aaForQuad != GrAAType::kNone) {
overallAAType = aaType;
}
- if (!mustFilter && this->filter() != GrSamplerState::Filter::kNearest) {
- mustFilter = quad.quadType() != GrQuad::Type::kAxisAligned ||
- GrTextureOp::GetFilterHasEffect(ctm, set[p].fSrcRect, set[p].fDstRect);
- }
// Calculate metadata for the entry
const SkRect* domainForQuad = nullptr;
@@ -594,6 +607,57 @@
namespace GrTextureOp {
+std::unique_ptr<GrDrawOp> MakeGeneral(GrRecordingContext* context,
+ sk_sp<GrTextureProxy> proxy,
+ sk_sp<GrColorSpaceXform> textureXform,
+ GrSamplerState::Filter filter,
+ const SkPMColor4f& color,
+ SkBlendMode blendMode,
+ GrAAType aaType,
+ GrQuadAAFlags aaFlags,
+ const GrQuad& deviceQuad,
+ const GrQuad& localQuad,
+ const SkRect* domain) {
+ // Apply optimizations that are valid whether or not using GrTextureOp or GrFillRectOp
+ if (domain && domain->contains(proxy->getWorstCaseBoundsRect())) {
+ // No need for a shader-based domain if hardware clamping achieves the same effect
+ domain = nullptr;
+ }
+
+ if (filter != GrSamplerState::Filter::kNearest && !filter_has_effect(localQuad, deviceQuad)) {
+ filter = GrSamplerState::Filter::kNearest;
+ }
+
+ if (blendMode == SkBlendMode::kSrcOver) {
+ return TextureOp::Make(context, std::move(proxy), std::move(textureXform), filter, color,
+ aaType, aaFlags, deviceQuad, localQuad, domain);
+ } else {
+ // Emulate complex blending using GrFillRectOp
+ GrPaint paint;
+ paint.setColor4f(color);
+ paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
+
+ std::unique_ptr<GrFragmentProcessor> fp;
+ if (domain) {
+ // Update domain to match what GrTextureOp computes during tessellation, using top-left
+ // as the origin so that it doesn't depend on final texture size (which the FP handles
+ // later, as well as accounting for the true origin).
+ SkRect correctedDomain;
+ compute_domain(Domain::kYes, filter, kTopLeft_GrSurfaceOrigin, *domain,
+ 1.f, 1.f, proxy->height(), &correctedDomain);
+ fp = GrTextureDomainEffect::Make(std::move(proxy), SkMatrix::I(), correctedDomain,
+ GrTextureDomain::kClamp_Mode, filter);
+ } else {
+ fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I(), filter);
+ }
+ fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform));
+ paint.addColorFragmentProcessor(std::move(fp));
+
+ return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
+ deviceQuad, localQuad);
+ }
+}
+
std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
sk_sp<GrTextureProxy> proxy,
GrSamplerState::Filter filter,
@@ -604,9 +668,11 @@
GrQuadAAFlags aaFlags,
SkCanvas::SrcRectConstraint constraint,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
- return TextureOp::Make(context, std::move(proxy), filter, color, srcRect, dstRect, aaType,
- aaFlags, constraint, viewMatrix, std::move(textureColorSpaceXform));
+ sk_sp<GrColorSpaceXform> textureColorSpaceXform,
+ SkBlendMode blendMode) {
+ return MakeGeneral(context, std::move(proxy), textureColorSpaceXform, filter, color, blendMode,
+ aaType, aaFlags, GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect),
+ constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr);
}
std::unique_ptr<GrDrawOp> MakeQuad(GrRecordingContext* context,
@@ -619,9 +685,11 @@
GrQuadAAFlags aaFlags,
const SkRect* domain,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> textureXform) {
- return TextureOp::Make(context, std::move(proxy), filter, color, srcQuad, dstQuad, aaType,
- aaFlags, domain, viewMatrix, std::move(textureXform));
+ sk_sp<GrColorSpaceXform> textureXform,
+ SkBlendMode blendMode) {
+ return MakeGeneral(context, std::move(proxy), textureXform, filter, color, blendMode,
+ aaType, aaFlags, GrQuad::MakeFromSkQuad(dstQuad, viewMatrix),
+ GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), domain);
}
std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
@@ -636,29 +704,6 @@
std::move(textureColorSpaceXform));
}
-bool GetFilterHasEffect(const SkMatrix& viewMatrix, const SkRect& srcRect, const SkRect& dstRect) {
- // Hypothetically we could disable bilerp filtering when flipping or rotating 90 degrees, but
- // that makes the math harder and we don't want to increase the overhead of the checks
- if (!viewMatrix.isScaleTranslate() ||
- viewMatrix.getScaleX() < 0.0f || viewMatrix.getScaleY() < 0.0f) {
- return true;
- }
-
- // Given the matrix conditions ensured above, this computes the device space coordinates for
- // the top left corner of dstRect and its size.
- SkScalar dw = viewMatrix.getScaleX() * dstRect.width();
- SkScalar dh = viewMatrix.getScaleY() * dstRect.height();
- SkScalar dl = viewMatrix.getScaleX() * dstRect.fLeft + viewMatrix.getTranslateX();
- SkScalar dt = viewMatrix.getScaleY() * dstRect.fTop + viewMatrix.getTranslateY();
-
- // Disable filtering when there is no scaling of the src rect and the src rect and dst rect
- // align fractionally. If we allow inverted src rects this logic needs to consider that.
- SkASSERT(srcRect.isSorted());
- return dw != srcRect.width() || dh != srcRect.height() ||
- SkScalarFraction(dl) != SkScalarFraction(srcRect.fLeft) ||
- SkScalarFraction(dt) != SkScalarFraction(srcRect.fTop);
-}
-
} // namespace GrTextureOp
#if GR_TEST_UTILS
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index 8061a35..2bf43b4 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -21,12 +21,29 @@
namespace GrTextureOp {
/**
- * Creates an op that draws a sub-rectangle of a texture. The passed color is modulated by the
- * texture's color. 'srcRect' specifies the rectangle of the texture to draw. 'dstRect' specifies
- * the rectangle to draw in local coords which will be transformed by 'viewMatrix' to be in device
- * space. 'viewMatrix' must be affine. If GrAAType is kCoverage then AA is applied to the edges
+ * Creates an op that draws a sub-quadrilateral of a texture. The passed color is modulated by the
+ * texture's color. 'deviceQuad' specifies the device-space coordinates to draw, using 'localQuad'
+ * to map into the proxy's texture space. If non-null, 'domain' represents the boundary for the
+ * strict src rect constraint. If GrAAType is kCoverage then AA is applied to the edges
* indicated by GrQuadAAFlags. Otherwise, GrQuadAAFlags is ignored.
+ *
+ * This is functionally very similar to GrFillRectOp::Make, except that the GrPaint has been
+ * deconstructed into the texture, filter, modulating color, and blend mode. When blend mode is
+ * src over, this will return a GrFillRectOp with a paint that samples the proxy.
*/
+std::unique_ptr<GrDrawOp> MakeGeneral(GrRecordingContext* context,
+ sk_sp<GrTextureProxy> proxy,
+ sk_sp<GrColorSpaceXform> textureXform,
+ GrSamplerState::Filter filter,
+ const SkPMColor4f& color,
+ SkBlendMode blendMode,
+ GrAAType aaType,
+ GrQuadAAFlags aaFlags,
+ const GrQuad& deviceQuad,
+ const GrQuad& localQuad,
+ const SkRect* domain = nullptr);
+
+// FIXME (michaelludwig) - To be removed
std::unique_ptr<GrDrawOp> Make(GrRecordingContext*,
sk_sp<GrTextureProxy>,
GrSamplerState::Filter,
@@ -37,11 +54,13 @@
GrQuadAAFlags,
SkCanvas::SrcRectConstraint,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> textureXform);
+ sk_sp<GrColorSpaceXform> textureXform,
+ SkBlendMode blendMode = SkBlendMode::kSrcOver);
// Generalizes the above subrect drawing operation to draw a subquad of an image, where srcQuad
// and dstQuad correspond to srcRect and dstRect. If domain is not null, this behaves as if it
// had a strict constraint relying on the given domain.
+// FIXME (michaelludwig) - To be removed
std::unique_ptr<GrDrawOp> MakeQuad(GrRecordingContext* context,
sk_sp<GrTextureProxy>,
GrSamplerState::Filter,
@@ -52,8 +71,10 @@
GrQuadAAFlags,
const SkRect* domain,
const SkMatrix& viewMatrix,
- sk_sp<GrColorSpaceXform> textureXform);
+ sk_sp<GrColorSpaceXform> textureXform,
+ SkBlendMode blendMode = SkBlendMode::kSrcOver);
+// Unlike the single-proxy factory, this only supports src-over blending.
std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext*,
const GrRenderTargetContext::TextureSetEntry[],
int cnt,
@@ -63,10 +84,4 @@
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> textureXform);
-/**
- * Returns true if bilerp texture filtering matters when rendering the src rect
- * texels to dst rect, with the given view matrix.
- */
-bool GetFilterHasEffect(const SkMatrix& viewMatrix, const SkRect& srcRect, const SkRect& dstRect);
-
}