aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/MultitextureImageBench.cpp52
-rw-r--r--src/gpu/GrPrimitiveProcessor.h6
-rw-r--r--src/gpu/GrRenderTargetContext.cpp8
-rw-r--r--src/gpu/GrRenderTargetContext.h5
-rw-r--r--src/gpu/SkGpuDevice_drawTexture.cpp15
-rw-r--r--src/gpu/ops/GrTextureOp.cpp318
-rw-r--r--src/gpu/ops/GrTextureOp.h2
7 files changed, 300 insertions, 106 deletions
diff --git a/bench/MultitextureImageBench.cpp b/bench/MultitextureImageBench.cpp
index d001cac774..2c87efb414 100644
--- a/bench/MultitextureImageBench.cpp
+++ b/bench/MultitextureImageBench.cpp
@@ -16,12 +16,16 @@
class MultitextureImages : public Benchmark {
public:
- MultitextureImages(int imageSize, int dstRectSize, bool disableMultitexturing)
+ MultitextureImages(int imageSize, int dstRectSize, bool disableMultitexturing, bool aa)
: fImageSize(imageSize)
, fDstRectSize(dstRectSize)
- , fDisableMultitexturing(disableMultitexturing) {
+ , fDisableMultitexturing(disableMultitexturing)
+ , fAA(aa) {
fName.appendf("multitexture_images_%dx%d_image_%dx%d_rect", imageSize, imageSize,
dstRectSize, dstRectSize);
+ if (aa) {
+ fName.append("_aa");
+ }
if (disableMultitexturing) {
fName.append("_disable_multitexturing");
}
@@ -60,6 +64,7 @@ protected:
SkPaint paint;
paint.setAlpha(0x40);
paint.setFilterQuality(kLow_SkFilterQuality);
+ paint.setAntiAlias(fAA);
for (int i = 0; i < loops; i++) {
for (int j = 0; j < kNumImages; ++j) {
SkVector translate = this->translation(i * kNumImages + j);
@@ -87,8 +92,9 @@ private:
SkVector translation(int i) const {
SkVector offset;
- offset.fX = i % kNumColumns * kTranslate;
- offset.fY = (i / kNumColumns) % kNumRows * kTranslate;
+ // Fractional offsets to ensure we can't ignore antialiasing.
+ offset.fX = i % kNumColumns * kTranslate + 0.1f;
+ offset.fY = (i / kNumColumns) % kNumRows * kTranslate + 0.1f;
return offset;
}
@@ -102,24 +108,32 @@ private:
int fImageSize;
int fDstRectSize;
bool fDisableMultitexturing;
+ bool fAA;
typedef Benchmark INHERITED;
};
-DEF_BENCH(return new MultitextureImages(128, 32, false));
-DEF_BENCH(return new MultitextureImages(128, 32, true));
-DEF_BENCH(return new MultitextureImages(128, 128, false));
-DEF_BENCH(return new MultitextureImages(128, 128, true));
-DEF_BENCH(return new MultitextureImages(128, 256, false));
-DEF_BENCH(return new MultitextureImages(128, 256, true));
-
-DEF_BENCH(return new MultitextureImages(512, 32, false));
-DEF_BENCH(return new MultitextureImages(512, 32, true));
-DEF_BENCH(return new MultitextureImages(512, 128, false));
-DEF_BENCH(return new MultitextureImages(512, 128, true));
-DEF_BENCH(return new MultitextureImages(512, 256, false));
-DEF_BENCH(return new MultitextureImages(512, 256, true));
-DEF_BENCH(return new MultitextureImages(512, 512, false));
-DEF_BENCH(return new MultitextureImages(512, 512, true));
+// Non-AA
+DEF_BENCH(return new MultitextureImages(128, 32, false, false));
+DEF_BENCH(return new MultitextureImages(128, 32, true, false));
+DEF_BENCH(return new MultitextureImages(128, 128, false, false));
+DEF_BENCH(return new MultitextureImages(128, 128, true, false));
+DEF_BENCH(return new MultitextureImages(128, 256, false, false));
+DEF_BENCH(return new MultitextureImages(128, 256, true, false));
+
+DEF_BENCH(return new MultitextureImages(512, 32, false, false));
+DEF_BENCH(return new MultitextureImages(512, 32, true, false));
+DEF_BENCH(return new MultitextureImages(512, 128, false, false));
+DEF_BENCH(return new MultitextureImages(512, 128, true, false));
+DEF_BENCH(return new MultitextureImages(512, 256, false, false));
+DEF_BENCH(return new MultitextureImages(512, 256, true, false));
+DEF_BENCH(return new MultitextureImages(512, 512, false, false));
+DEF_BENCH(return new MultitextureImages(512, 512, true, false));
+
+// AA
+DEF_BENCH(return new MultitextureImages(512, 512, true, true));
+DEF_BENCH(return new MultitextureImages(512, 512, false, true));
+DEF_BENCH(return new MultitextureImages(128, 32, true, true));
+DEF_BENCH(return new MultitextureImages(128, 32, false, true));
#endif
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index f480110df5..22c65fa249 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -49,7 +49,11 @@ public:
return GrShaderVar(fName, GrVertexAttribTypeToSLType(fType),
GrShaderVar::kIn_TypeModifier);
}
- const char* fName;
+ bool isInitialized() const { return SkToBool(fName); }
+ Attribute() = default;
+ Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate)
+ : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {}
+ const char* fName = nullptr;
GrVertexAttribType fType;
int fOffsetInRecord;
InputRate fInputRate;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index c985e964e8..b0b117f914 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -766,7 +766,7 @@ static bool must_filter(const SkRect& src, const SkRect& dst, const SkMatrix& ct
void GrRenderTargetContext::drawTextureAffine(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
GrSamplerState::Filter filter, GrColor color,
- const SkRect& srcRect, const SkRect& dstRect,
+ const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> colorSpaceXform) {
ASSERT_SINGLE_OWNER
@@ -785,9 +785,9 @@ void GrRenderTargetContext::drawTextureAffine(const GrClip& clip, sk_sp<GrTextur
}
bool allowSRGB = SkToBool(this->colorSpaceInfo().colorSpace());
- this->addDrawOp(clip, GrTextureOp::Make(std::move(proxy), filter, color, clippedSrcRect,
- clippedDstRect, viewMatrix, std::move(colorSpaceXform),
- allowSRGB));
+ this->addDrawOp(
+ clip, GrTextureOp::Make(std::move(proxy), filter, color, clippedSrcRect, clippedDstRect,
+ aa, viewMatrix, std::move(colorSpaceXform), allowSRGB));
}
void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h
index 6215262177..2ae52b922c 100644
--- a/src/gpu/GrRenderTargetContext.h
+++ b/src/gpu/GrRenderTargetContext.h
@@ -145,11 +145,10 @@ public:
* Creates an op that draws a subrectangle 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
- * device space. The edges of the rendered rectangle are not antialiased. This asserts that the
- * view matrix does not have perspective.
+ * device space. This asserts that the view matrix does not have perspective.
*/
void drawTextureAffine(const GrClip& clip, sk_sp<GrTextureProxy>, GrSamplerState::Filter,
- GrColor, const SkRect& srcRect, const SkRect& dstRect,
+ GrColor, const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform>);
/**
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index bedd292a58..f8e5f74311 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -94,14 +94,13 @@ static bool can_ignore_bilerp_constraint(const GrTextureProducer& producer,
static bool can_use_draw_texture_affine(const SkPaint& paint, const SkMatrix& ctm,
SkCanvas::SrcRectConstraint constraint) {
return (!paint.getColorFilter() && !paint.getShader() && !paint.getMaskFilter() &&
- !paint.getImageFilter() && !paint.isAntiAlias() &&
- paint.getFilterQuality() < kMedium_SkFilterQuality &&
+ !paint.getImageFilter() && paint.getFilterQuality() < kMedium_SkFilterQuality &&
paint.getBlendMode() == SkBlendMode::kSrcOver && !ctm.hasPerspective() &&
SkCanvas::kFast_SrcRectConstraint == constraint);
}
static void draw_texture_affine(const SkPaint& paint, const SkMatrix& ctm, const SkRect* src,
- const SkRect* dst, sk_sp<GrTextureProxy> proxy,
+ const SkRect* dst, GrAA aa, sk_sp<GrTextureProxy> proxy,
SkColorSpace* colorSpace, const GrClip& clip,
GrRenderTargetContext* rtc) {
SkASSERT(!(SkToBool(src) && !SkToBool(dst)));
@@ -131,7 +130,7 @@ static void draw_texture_affine(const SkPaint& paint, const SkMatrix& ctm, const
GrColor color = GrPixelConfigIsAlphaOnly(proxy->config())
? SkColorToPremulGrColor(paint.getColor())
: SkColorAlphaToGrColor(paint.getColor());
- rtc->drawTextureAffine(clip, std::move(proxy), filter, color, srcRect, dstRect, ctm,
+ rtc->drawTextureAffine(clip, std::move(proxy), filter, color, srcRect, dstRect, aa, ctm,
std::move(csxf));
}
@@ -143,8 +142,8 @@ void SkGpuDevice::drawPinnedTextureProxy(sk_sp<GrTextureProxy> proxy, uint32_t p
SkCanvas::SrcRectConstraint constraint,
const SkMatrix& viewMatrix, const SkPaint& paint) {
if (can_use_draw_texture_affine(paint, this->ctm(), constraint)) {
- draw_texture_affine(paint, viewMatrix, srcRect, dstRect, std::move(proxy), colorSpace,
- this->clip(), fRenderTargetContext.get());
+ draw_texture_affine(paint, viewMatrix, srcRect, dstRect, GrAA(paint.isAntiAlias()),
+ std::move(proxy), colorSpace, this->clip(), fRenderTargetContext.get());
return;
}
GrTextureAdjuster adjuster(this->context(), std::move(proxy), alphaType, pinnedUniqueID,
@@ -166,8 +165,8 @@ void SkGpuDevice::drawTextureMaker(GrTextureMaker* maker, int imageW, int imageH
if (!proxy) {
return;
}
- draw_texture_affine(paint, viewMatrix, srcRect, dstRect, std::move(proxy), cs.get(),
- this->clip(), fRenderTargetContext.get());
+ draw_texture_affine(paint, viewMatrix, srcRect, dstRect, GrAA(paint.isAntiAlias()),
+ std::move(proxy), cs.get(), this->clip(), fRenderTargetContext.get());
return;
}
this->drawTextureProducer(maker, srcRect, dstRect, constraint, viewMatrix, paint);
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index 5ed02cc1a5..6d735f51af 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -20,9 +20,13 @@
#include "GrTextureProxy.h"
#include "SkGr.h"
#include "SkMathPriv.h"
+#include "SkPoint.h"
+#include "SkPoint3.h"
#include "glsl/GrGLSLColorSpaceXformHelper.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLVarying.h"
+#include "glsl/GrGLSLVertexGeoBuilder.h"
namespace {
@@ -38,12 +42,25 @@ public:
SkPoint fTextureCoords;
GrColor fColor;
};
+ struct AAVertex {
+ SkPoint fPosition;
+ SkPoint fTextureCoords;
+ SkPoint3 fEdges[4];
+ GrColor fColor;
+ };
struct MultiTextureVertex {
SkPoint fPosition;
int fTextureIdx;
SkPoint fTextureCoords;
GrColor fColor;
};
+ struct AAMultiTextureVertex {
+ SkPoint fPosition;
+ int fTextureIdx;
+ SkPoint fTextureCoords;
+ SkPoint3 fEdges[4];
+ GrColor fColor;
+ };
// Maximum number of textures supported by this op. Must also be checked against the caps
// limit. These numbers were based on some limited experiments on a HP Z840 and Pixel XL 2016
@@ -59,7 +76,7 @@ public:
}
static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt,
- sk_sp<GrColorSpaceXform> csxf,
+ sk_sp<GrColorSpaceXform> csxf, GrAA aa,
const GrSamplerState::Filter filters[],
const GrShaderCaps& caps) {
// We use placement new to avoid always allocating space for kMaxTextures TextureSampler
@@ -68,7 +85,7 @@ public:
size_t size = sizeof(TextureGeometryProcessor) + sizeof(TextureSampler) * (samplerCnt - 1);
void* mem = GrGeometryProcessor::operator new(size);
return sk_sp<TextureGeometryProcessor>(new (mem) TextureGeometryProcessor(
- proxies, proxyCnt, samplerCnt, std::move(csxf), filters, caps));
+ proxies, proxyCnt, samplerCnt, std::move(csxf), aa, filters, caps));
}
~TextureGeometryProcessor() override {
@@ -82,6 +99,7 @@ public:
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
+ b->add32(static_cast<uint32_t>(this->aa()));
}
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override {
@@ -149,13 +167,36 @@ public:
&fColorSpaceXformHelper);
}
args.fFragBuilder->codeAppend(";");
- args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+ if (GrAA::kYes == textureGP.aa()) {
+ GrGLSLVarying aaDistVarying(kFloat4_GrSLType,
+ GrGLSLVarying::Scope::kVertToFrag);
+ args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
+ args.fVertBuilder->codeAppendf(
+ R"(%s = float4(dot(aaEdge0.xy, %s.xy) + aaEdge0.z,
+ dot(aaEdge1.xy, %s.xy) + aaEdge1.z,
+ dot(aaEdge2.xy, %s.xy) + aaEdge2.z,
+ dot(aaEdge3.xy, %s.xy) + aaEdge3.z);)",
+ aaDistVarying.vsOut(), textureGP.fPositions.fName,
+ textureGP.fPositions.fName, textureGP.fPositions.fName,
+ textureGP.fPositions.fName);
+
+ args.fFragBuilder->codeAppendf(
+ "float mindist = min(min(%s.x, %s.y), min(%s.z, %s.w));",
+ aaDistVarying.fsIn(), aaDistVarying.fsIn(), aaDistVarying.fsIn(),
+ aaDistVarying.fsIn());
+ args.fFragBuilder->codeAppendf("%s = float4(clamp(mindist, 0, 1));",
+ args.fOutputCoverage);
+ } else {
+ args.fFragBuilder->codeAppendf("%s = float4(1);", args.fOutputCoverage);
+ }
}
GrGLSLColorSpaceXformHelper fColorSpaceXformHelper;
};
return new GLSLProcessor;
}
+ GrAA aa() const { return GrAA(fAAEdges[0].isInitialized()); }
+
private:
// This exists to reduce the number of shaders generated. It does some rounding of sampler
// counts.
@@ -173,10 +214,9 @@ private:
}
TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt,
- sk_sp<GrColorSpaceXform> csxf, const GrSamplerState::Filter filters[],
- const GrShaderCaps& caps)
- : INHERITED(kTextureGeometryProcessor_ClassID)
- , fColorSpaceXform(std::move(csxf)) {
+ sk_sp<GrColorSpaceXform> csxf, GrAA aa,
+ const GrSamplerState::Filter filters[], const GrShaderCaps& caps)
+ : INHERITED(kTextureGeometryProcessor_ClassID), fColorSpaceXform(std::move(csxf)) {
SkASSERT(proxyCnt > 0 && samplerCnt >= proxyCnt);
fPositions = this->addVertexAttrib("position", kFloat2_GrVertexAttribType);
fSamplers[0].reset(std::move(proxies[0]), filters[0]);
@@ -200,6 +240,12 @@ private:
}
fTextureCoords = this->addVertexAttrib("textureCoords", kFloat2_GrVertexAttribType);
+ if (GrAA::kYes == aa) {
+ fAAEdges[0] = this->addVertexAttrib("aaEdge0", kFloat3_GrVertexAttribType);
+ fAAEdges[1] = this->addVertexAttrib("aaEdge1", kFloat3_GrVertexAttribType);
+ fAAEdges[2] = this->addVertexAttrib("aaEdge2", kFloat3_GrVertexAttribType);
+ fAAEdges[3] = this->addVertexAttrib("aaEdge3", kFloat3_GrVertexAttribType);
+ }
fColors = this->addVertexAttrib("color", kUByte4_norm_GrVertexAttribType);
}
@@ -207,12 +253,148 @@ private:
Attribute fTextureIdx;
Attribute fTextureCoords;
Attribute fColors;
+ Attribute fAAEdges[4];
sk_sp<GrColorSpaceXform> fColorSpaceXform;
TextureSampler fSamplers[1];
typedef GrGeometryProcessor INHERITED;
};
+namespace {
+// This is a class soley so it can be partially specialized (functions cannot be).
+template<GrAA, typename Vertex> class VertexAAHandler;
+
+template<typename Vertex> class VertexAAHandler<GrAA::kNo, Vertex> {
+public:
+ static void AssignPositionsAndTexCoords(Vertex* vertices, const GrQuad& quad,
+ const SkRect& texRect) {
+ vertices[0].fPosition = quad.point(0);
+ vertices[0].fTextureCoords = {texRect.fLeft, texRect.fTop};
+ vertices[1].fPosition = quad.point(1);
+ vertices[1].fTextureCoords = {texRect.fLeft, texRect.fBottom};
+ vertices[2].fPosition = quad.point(2);
+ vertices[2].fTextureCoords = {texRect.fRight, texRect.fTop};
+ vertices[3].fPosition = quad.point(3);
+ vertices[3].fTextureCoords = {texRect.fRight, texRect.fBottom};
+ }
+};
+
+template<typename Vertex> class VertexAAHandler<GrAA::kYes, Vertex> {
+public:
+ static void AssignPositionsAndTexCoords(Vertex* vertices, const GrQuad& quad,
+ const SkRect& texRect) {
+ // We compute the four edge equations for quad, then outset them and compute a new quad
+ // as the intersection points of the outset edges.
+
+ // GrQuad is in tristip order but we want the points to be in a fan order, so swap 2 and 3.
+ Sk4f xs(quad.point(0).fX, quad.point(1).fX, quad.point(3).fX, quad.point(2).fX);
+ Sk4f ys(quad.point(0).fY, quad.point(1).fY, quad.point(3).fY, quad.point(2).fY);
+ Sk4f xsrot = SkNx_shuffle<1, 2, 3, 0>(xs);
+ Sk4f ysrot = SkNx_shuffle<1, 2, 3, 0>(ys);
+ Sk4f normXs = ysrot - ys;
+ Sk4f normYs = xs - xsrot;
+ Sk4f ds = xsrot * ys - ysrot * xs;
+ Sk4f invNormLengths = (normXs * normXs + normYs * normYs).rsqrt();
+ float test = normXs[0] * xs[2] + normYs[0] * ys[2] + ds[0];
+ // Make sure the edge equations have their normals facing into the quad in device space
+ if (test < 0) {
+ invNormLengths = -invNormLengths;
+ }
+ normXs *= invNormLengths;
+ normYs *= invNormLengths;
+ ds *= invNormLengths;
+
+ // Here is the bloat. This makes our edge equations compute coverage without requiring a
+ // half pixel offset and is also used to compute the bloated quad that will cover all
+ // pixels.
+ ds += Sk4f(0.5f);
+
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ vertices[j].fEdges[i].fX = normXs[i];
+ vertices[j].fEdges[i].fY = normYs[i];
+ vertices[j].fEdges[i].fZ = ds[i];
+ }
+ }
+
+ // Reverse the process to compute the points of the bloated quad from the edge equations.
+ // This time the inputs don't have 1s as their third coord and we want to homogenize rather
+ // than normalize the output since we need a GrQuad with 2D points.
+ xsrot = SkNx_shuffle<3, 0, 1, 2>(normXs);
+ ysrot = SkNx_shuffle<3, 0, 1, 2>(normYs);
+ Sk4f dsrot = SkNx_shuffle<3, 0, 1, 2>(ds);
+ xs = ysrot * ds - normYs * dsrot;
+ ys = normXs * dsrot - xsrot * ds;
+ ds = xsrot * normYs - ysrot * normXs;
+ ds = ds.invert();
+ xs *= ds;
+ ys *= ds;
+
+ // Go back to tri strip order when writing out the bloated quad to vertex positions.
+ vertices[0].fPosition = {xs[0], ys[0]};
+ vertices[1].fPosition = {xs[1], ys[1]};
+ vertices[3].fPosition = {xs[2], ys[2]};
+ vertices[2].fPosition = {xs[3], ys[3]};
+
+ AssignTexCoords(vertices, quad, texRect);
+ }
+
+private:
+ static void AssignTexCoords(Vertex* vertices, const GrQuad& quad, const SkRect& tex) {
+ SkMatrix q = SkMatrix::MakeAll(quad.point(0).fX, quad.point(1).fX, quad.point(2).fX,
+ quad.point(0).fY, quad.point(1).fY, quad.point(2).fY,
+ 1.f, 1.f, 1.f);
+ SkMatrix qinv;
+ if (!q.invert(&qinv)) {
+ return;
+ }
+ SkMatrix t = SkMatrix::MakeAll(tex.fLeft, tex.fLeft, tex.fRight,
+ tex.fTop, tex.fBottom, tex.fTop,
+ 1.f, 1.f, 1.f);
+ SkMatrix map;
+ map.setConcat(t, qinv);
+ SkMatrixPriv::MapPointsWithStride(map, &vertices[0].fTextureCoords, sizeof(Vertex),
+ &vertices[0].fPosition, sizeof(Vertex), 4);
+ }
+};
+
+template <typename Vertex, bool IsMultiTex> struct TexIdAssigner;
+
+template <typename Vertex> struct TexIdAssigner<Vertex, true> {
+ static void Assign(Vertex* vertices, int textureIdx) {
+ vertices[0].fTextureIdx = textureIdx;
+ vertices[1].fTextureIdx = textureIdx;
+ vertices[2].fTextureIdx = textureIdx;
+ vertices[3].fTextureIdx = textureIdx;
+ }
+};
+
+template <typename Vertex> struct TexIdAssigner<Vertex, false> {
+ static void Assign(Vertex* vertices, int textureIdx) {}
+};
+} // anonymous namespace
+
+template <typename Vertex, bool IsMultiTex, GrAA AA>
+static void tessellate_quad(const GrQuad& devQuad, const SkRect& srcRect, GrColor color,
+ GrSurfaceOrigin origin, Vertex* vertices, SkScalar iw, SkScalar ih,
+ int textureIdx) {
+ SkRect texRect = {
+ iw * srcRect.fLeft,
+ ih * srcRect.fTop,
+ iw * srcRect.fRight,
+ ih * srcRect.fBottom
+ };
+ if (origin == kBottomLeft_GrSurfaceOrigin) {
+ texRect.fTop = 1.f - texRect.fTop;
+ texRect.fBottom = 1.f - texRect.fBottom;
+ }
+ VertexAAHandler<AA, Vertex>::AssignPositionsAndTexCoords(vertices, devQuad, texRect);
+ vertices[0].fColor = color;
+ vertices[1].fColor = color;
+ vertices[2].fColor = color;
+ vertices[3].fColor = color;
+ TexIdAssigner<Vertex, IsMultiTex>::Assign(vertices, textureIdx);
+}
/**
* Op that implements GrTextureOp::Make. It draws textured quads. Each quad can modulate against a
* the texture by color. The blend with the destination is always src-over. The edges are non-AA.
@@ -221,11 +403,11 @@ class TextureOp final : public GrMeshDrawOp {
public:
static std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy,
GrSamplerState::Filter filter, GrColor color,
- const SkRect srcRect, const SkRect dstRect,
+ const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf,
bool allowSRBInputs) {
return std::unique_ptr<GrDrawOp>(new TextureOp(std::move(proxy), filter, color, srcRect,
- dstRect, viewMatrix, std::move(csxf),
+ dstRect, aa, viewMatrix, std::move(csxf),
allowSRBInputs));
}
@@ -298,22 +480,23 @@ private:
#if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007
__attribute__((no_sanitize("float-cast-overflow")))
#endif
- size_t RectSizeAsSizeT(const SkRect &rect) {;
+ size_t RectSizeAsSizeT(const SkRect& rect) {;
return static_cast<size_t>(SkTMax(rect.width(), 1.f) * SkTMax(rect.height(), 1.f));
}
static constexpr int kMaxTextures = TextureGeometryProcessor::kMaxTextures;
TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color,
- const SkRect& srcRect, const SkRect& dstRect, const SkMatrix& viewMatrix,
+ const SkRect& srcRect, const SkRect& dstRect, GrAA aa, const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> csxf, bool allowSRGBInputs)
: INHERITED(ClassID())
, fColorSpaceXform(std::move(csxf))
, fProxy0(proxy.release())
, fFilter0(filter)
, fProxyCnt(1)
- , fFinalized(false)
- , fAllowSRGBInputs(allowSRGBInputs) {
+ , fAA(aa == GrAA::kYes ? 1 : 0)
+ , fFinalized(0)
+ , fAllowSRGBInputs(allowSRGBInputs ? 1 : 0) {
Draw& draw = fDraws.push_back();
draw.fSrcRect = srcRect;
draw.fTextureIdx = 0;
@@ -339,7 +522,7 @@ __attribute__((no_sanitize("float-cast-overflow")))
sk_sp<GrGeometryProcessor> gp =
TextureGeometryProcessor::Make(proxiesSPs, fProxyCnt, std::move(fColorSpaceXform),
- filters, *target->caps().shaderCaps());
+ this->aa(), filters, *target->caps().shaderCaps());
GrPipeline::InitArgs args;
args.fProxy = target->proxy();
args.fCaps = &target->caps();
@@ -356,35 +539,28 @@ __attribute__((no_sanitize("float-cast-overflow")))
return;
}
if (1 == fProxyCnt) {
- SkASSERT(gp->getVertexStride() == sizeof(TextureGeometryProcessor::Vertex));
- for (int i = 0; i < fDraws.count(); ++i) {
+ GrSurfaceOrigin origin = proxies[0]->origin();
+ GrTexture* texture = proxies[0]->priv().peekTexture();
+ float iw = 1.f / texture->width();
+ float ih = 1.f / texture->height();
+ if (GrAA::kYes == this->aa()) {
+ SkASSERT(gp->getVertexStride() == sizeof(TextureGeometryProcessor::AAVertex));
+ auto vertices = static_cast<TextureGeometryProcessor::AAVertex*>(vdata);
+ for (int i = 0; i < fDraws.count(); ++i) {
+ tessellate_quad<TextureGeometryProcessor::AAVertex, false, GrAA::kYes>(
+ fDraws[i].fQuad, fDraws[i].fSrcRect, fDraws[i].fColor, origin,
+ vertices + 4 * i, iw, ih, 0);
+ }
+ } else {
+ SkASSERT(gp->getVertexStride() == sizeof(TextureGeometryProcessor::Vertex));
auto vertices = static_cast<TextureGeometryProcessor::Vertex*>(vdata);
- GrTexture* texture = proxies[0]->priv().peekTexture();
- float iw = 1.f / texture->width();
- float ih = 1.f / texture->height();
- float tl = iw * fDraws[i].fSrcRect.fLeft;
- float tr = iw * fDraws[i].fSrcRect.fRight;
- float tt = ih * fDraws[i].fSrcRect.fTop;
- float tb = ih * fDraws[i].fSrcRect.fBottom;
- if (proxies[0]->origin() == kBottomLeft_GrSurfaceOrigin) {
- tt = 1.f - tt;
- tb = 1.f - tb;
+ for (int i = 0; i < fDraws.count(); ++i) {
+ tessellate_quad<TextureGeometryProcessor::Vertex, false, GrAA::kNo>(
+ fDraws[i].fQuad, fDraws[i].fSrcRect, fDraws[i].fColor, origin,
+ vertices + 4 * i, iw, ih, 0);
}
- vertices[0 + 4 * i].fPosition = fDraws[i].fQuad.points()[0];
- vertices[0 + 4 * i].fTextureCoords = {tl, tt};
- vertices[0 + 4 * i].fColor = fDraws[i].fColor;
- vertices[1 + 4 * i].fPosition = fDraws[i].fQuad.points()[1];
- vertices[1 + 4 * i].fTextureCoords = {tl, tb};
- vertices[1 + 4 * i].fColor = fDraws[i].fColor;
- vertices[2 + 4 * i].fPosition = fDraws[i].fQuad.points()[2];
- vertices[2 + 4 * i].fTextureCoords = {tr, tt};
- vertices[2 + 4 * i].fColor = fDraws[i].fColor;
- vertices[3 + 4 * i].fPosition = fDraws[i].fQuad.points()[3];
- vertices[3 + 4 * i].fTextureCoords = {tr, tb};
- vertices[3 + 4 * i].fColor = fDraws[i].fColor;
}
} else {
- SkASSERT(gp->getVertexStride() == sizeof(TextureGeometryProcessor::MultiTextureVertex));
GrTexture* textures[kMaxTextures];
float iw[kMaxTextures];
float ih[kMaxTextures];
@@ -393,33 +569,29 @@ __attribute__((no_sanitize("float-cast-overflow")))
iw[t] = 1.f / textures[t]->width();
ih[t] = 1.f / textures[t]->height();
}
- for (int i = 0; i < fDraws.count(); ++i) {
- int t = fDraws[i].fTextureIdx;
+ if (GrAA::kYes == this->aa()) {
+ SkASSERT(gp->getVertexStride() ==
+ sizeof(TextureGeometryProcessor::AAMultiTextureVertex));
+ auto vertices = static_cast<TextureGeometryProcessor::AAMultiTextureVertex*>(vdata);
+ for (int i = 0; i < fDraws.count(); ++i) {
+ auto tidx = fDraws[i].fTextureIdx;
+ GrSurfaceOrigin origin = proxies[tidx]->origin();
+ tessellate_quad<TextureGeometryProcessor::AAMultiTextureVertex, true,
+ GrAA::kYes>(fDraws[i].fQuad, fDraws[i].fSrcRect,
+ fDraws[i].fColor, origin, vertices + 4 * i,
+ iw[tidx], ih[tidx], tidx);
+ }
+ } else {
+ SkASSERT(gp->getVertexStride() ==
+ sizeof(TextureGeometryProcessor::MultiTextureVertex));
auto vertices = static_cast<TextureGeometryProcessor::MultiTextureVertex*>(vdata);
- float tl = iw[t] * fDraws[i].fSrcRect.fLeft;
- float tr = iw[t] * fDraws[i].fSrcRect.fRight;
- float tt = ih[t] * fDraws[i].fSrcRect.fTop;
- float tb = ih[t] * fDraws[i].fSrcRect.fBottom;
- if (proxies[t]->origin() == kBottomLeft_GrSurfaceOrigin) {
- tt = 1.f - tt;
- tb = 1.f - tb;
+ for (int i = 0; i < fDraws.count(); ++i) {
+ auto tidx = fDraws[i].fTextureIdx;
+ GrSurfaceOrigin origin = proxies[tidx]->origin();
+ tessellate_quad<TextureGeometryProcessor::MultiTextureVertex, true, GrAA::kNo>(
+ fDraws[i].fQuad, fDraws[i].fSrcRect, fDraws[i].fColor, origin,
+ vertices + 4 * i, iw[tidx], ih[tidx], tidx);
}
- vertices[0 + 4 * i].fPosition = fDraws[i].fQuad.points()[0];
- vertices[0 + 4 * i].fTextureIdx = t;
- vertices[0 + 4 * i].fTextureCoords = {tl, tt};
- vertices[0 + 4 * i].fColor = fDraws[i].fColor;
- vertices[1 + 4 * i].fPosition = fDraws[i].fQuad.points()[1];
- vertices[1 + 4 * i].fTextureIdx = t;
- vertices[1 + 4 * i].fTextureCoords = {tl, tb};
- vertices[1 + 4 * i].fColor = fDraws[i].fColor;
- vertices[2 + 4 * i].fPosition = fDraws[i].fQuad.points()[2];
- vertices[2 + 4 * i].fTextureIdx = t;
- vertices[2 + 4 * i].fTextureCoords = {tr, tt};
- vertices[2 + 4 * i].fColor = fDraws[i].fColor;
- vertices[3 + 4 * i].fPosition = fDraws[i].fQuad.points()[3];
- vertices[3 + 4 * i].fTextureIdx = t;
- vertices[3 + 4 * i].fTextureCoords = {tr, tb};
- vertices[3 + 4 * i].fColor = fDraws[i].fColor;
}
}
GrPrimitiveType primitiveType =
@@ -446,6 +618,9 @@ __attribute__((no_sanitize("float-cast-overflow")))
if (!GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get())) {
return false;
}
+ if (this->fAA != that->fAA) {
+ return false;
+ }
// Because of an issue where GrColorSpaceXform adds the same function every time it is used
// in a texture lookup, we only allow multiple textures when there is no transform.
if (TextureGeometryProcessor::SupportsMultitexture(shaderCaps) && !fColorSpaceXform &&
@@ -560,6 +735,8 @@ __attribute__((no_sanitize("float-cast-overflow")))
return newProxyCnt;
}
+ GrAA aa() const { return static_cast<GrAA>(fAA); }
+
GrTextureProxy* const* proxies() const { return fProxyCnt > 1 ? fProxyArray : &fProxy0; }
const GrSamplerState::Filter* filters() const {
@@ -585,12 +762,12 @@ __attribute__((no_sanitize("float-cast-overflow")))
GrTextureProxy** fProxyArray;
};
size_t fMaxApproxDstPixelArea;
- // The next four members should pack.
GrSamplerState::Filter fFilter0;
uint8_t fProxyCnt;
+ unsigned fAA : 1;
// Used to track whether fProxy is ref'ed or has a pending IO after finalize() is called.
- uint8_t fFinalized;
- uint8_t fAllowSRGBInputs;
+ unsigned fFinalized : 1;
+ unsigned fAllowSRGBInputs : 1;
typedef GrMeshDrawOp INHERITED;
};
@@ -603,11 +780,11 @@ constexpr int TextureOp::kMaxTextures;
namespace GrTextureOp {
std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter,
- GrColor color, const SkRect& srcRect, const SkRect& dstRect,
+ GrColor color, const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf,
bool allowSRGBInputs) {
SkASSERT(!viewMatrix.hasPerspective());
- return TextureOp::Make(std::move(proxy), filter, color, srcRect, dstRect, viewMatrix,
+ return TextureOp::Make(std::move(proxy), filter, color, srcRect, dstRect, aa, viewMatrix,
std::move(csxf), allowSRGBInputs);
}
@@ -639,7 +816,8 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
static_cast<uint32_t>(GrSamplerState::Filter::kMipMap) + 1);
auto csxf = GrTest::TestColorXform(random);
bool allowSRGBInputs = random->nextBool();
- return GrTextureOp::Make(std::move(proxy), filter, color, srcRect, rect, viewMatrix,
+ GrAA aa = GrAA(random->nextBool());
+ return GrTextureOp::Make(std::move(proxy), filter, color, srcRect, rect, aa, viewMatrix,
std::move(csxf), allowSRGBInputs);
}
diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h
index d5a766b30f..9a03c8c6e1 100644
--- a/src/gpu/ops/GrTextureOp.h
+++ b/src/gpu/ops/GrTextureOp.h
@@ -23,7 +23,7 @@ namespace GrTextureOp {
* space. 'viewMatrix' must be affine.
*/
std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy>, GrSamplerState::Filter, GrColor,
- const SkRect& srcRect, const SkRect& dstRect,
+ const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform>,
bool allowSRGBInputs);
}