Add support for SkCanvas::kStrict_SrcRectConstraint to GrTextureOp.
Change-Id: I8faa2838b3110b8080ac48bbe223240e3fb22998 Reviewed-on: https://skia-review.googlesource.com/129762 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
6ddbafcc89
commit
a0047bcff7
@ -28,7 +28,7 @@ public:
|
||||
protected:
|
||||
SkString onShortName() override { return SkString("persp_images"); }
|
||||
|
||||
SkISize onISize() override { return SkISize::Make(1150, 880); }
|
||||
SkISize onISize() override { return SkISize::Make(1150, 1280); }
|
||||
|
||||
void onOnceBeforeDraw() override {
|
||||
fImages.push_back(make_image1());
|
||||
@ -60,7 +60,13 @@ protected:
|
||||
}
|
||||
canvas->translate(-bounds.fLeft + 10.f, -bounds.fTop + 10.f);
|
||||
canvas->save();
|
||||
for (auto subrect : {false, true}) {
|
||||
enum class DrawType {
|
||||
kDrawImage,
|
||||
kDrawImageRectStrict,
|
||||
kDrawImageRectFast,
|
||||
};
|
||||
for (auto type :
|
||||
{DrawType::kDrawImage, DrawType::kDrawImageRectStrict, DrawType::kDrawImageRectFast}) {
|
||||
for (const auto& m : matrices) {
|
||||
for (auto aa : {false, true}) {
|
||||
paint.setAntiAlias(aa);
|
||||
@ -70,14 +76,22 @@ protected:
|
||||
paint.setFilterQuality(filter);
|
||||
canvas->save();
|
||||
canvas->concat(m);
|
||||
if (subrect) {
|
||||
SkRect src = {img->width() / 4.f, img->height() / 4.f,
|
||||
3.f * img->width() / 4.f, 3.f * img->height() / 4};
|
||||
SkRect dst = {0, 0,
|
||||
3.f / 4.f * img->width(), 3.f / 4.f * img->height()};
|
||||
canvas->drawImageRect(img, src, dst, &paint);
|
||||
} else {
|
||||
canvas->drawImage(img, 0, 0, &paint);
|
||||
SkRect src = {img->width() / 4.f, img->height() / 4.f,
|
||||
3.f * img->width() / 4.f, 3.f * img->height() / 4};
|
||||
SkRect dst = {0, 0,
|
||||
3.f / 4.f * img->width(), 3.f / 4.f * img->height()};
|
||||
switch (type) {
|
||||
case DrawType::kDrawImage:
|
||||
canvas->drawImage(img, 0, 0, &paint);
|
||||
break;
|
||||
case DrawType::kDrawImageRectStrict:
|
||||
canvas->drawImageRect(img, src, dst, &paint,
|
||||
SkCanvas::kStrict_SrcRectConstraint);
|
||||
break;
|
||||
case DrawType::kDrawImageRectFast:
|
||||
canvas->drawImageRect(img, src, dst, &paint,
|
||||
SkCanvas::kFast_SrcRectConstraint);
|
||||
break;
|
||||
}
|
||||
canvas->restore();
|
||||
++n;
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
|
||||
SkPoint3 point(int i) const { return {fX[i], fY[i], fW[i]}; }
|
||||
|
||||
SkRect bounds() {
|
||||
SkRect bounds() const {
|
||||
auto x = this->x4f() * this->iw4f();
|
||||
auto y = this->y4f() * this->iw4f();
|
||||
return {x.min(), y.min(), x.max(), y.max()};
|
||||
|
@ -766,6 +766,7 @@ static bool must_filter(const SkRect& src, const SkRect& dst, const SkMatrix& ct
|
||||
void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
|
||||
GrSamplerState::Filter filter, GrColor color,
|
||||
const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> colorSpaceXform) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
@ -783,9 +784,9 @@ void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy
|
||||
}
|
||||
GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
|
||||
bool allowSRGB = SkToBool(this->colorSpaceInfo().colorSpace());
|
||||
this->addDrawOp(
|
||||
clip, GrTextureOp::Make(std::move(proxy), filter, color, clippedSrcRect, clippedDstRect,
|
||||
aaType, viewMatrix, std::move(colorSpaceXform), allowSRGB));
|
||||
this->addDrawOp(clip, GrTextureOp::Make(std::move(proxy), filter, color, clippedSrcRect,
|
||||
clippedDstRect, aaType, constraint, viewMatrix,
|
||||
std::move(colorSpaceXform), allowSRGB));
|
||||
}
|
||||
|
||||
void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
|
||||
|
@ -150,7 +150,8 @@ public:
|
||||
*/
|
||||
void drawTexture(const GrClip& clip, sk_sp<GrTextureProxy>, GrSamplerState::Filter, GrColor,
|
||||
const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
|
||||
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform>);
|
||||
SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform>);
|
||||
|
||||
/**
|
||||
* Draw a roundrect using a paint.
|
||||
|
@ -87,20 +87,19 @@ static bool can_ignore_bilerp_constraint(const GrTextureProducer& producer,
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the paint, matrix, and constraint are compatible with using
|
||||
* GrRenderTargetContext::drawTexture. It is more efficient than the GrTextureProducer
|
||||
* general case.
|
||||
* Checks whether the paint is compatible with using GrRenderTargetContext::drawTexture. It is more
|
||||
* efficient than the GrTextureProducer general case.
|
||||
*/
|
||||
static bool can_use_draw_texture(const SkPaint& paint, GrAA aa, const SkMatrix& ctm,
|
||||
SkCanvas::SrcRectConstraint constraint) {
|
||||
static bool can_use_draw_texture(const SkPaint& paint) {
|
||||
return (!paint.getColorFilter() && !paint.getShader() && !paint.getMaskFilter() &&
|
||||
!paint.getImageFilter() && paint.getFilterQuality() < kMedium_SkFilterQuality &&
|
||||
paint.getBlendMode() == SkBlendMode::kSrcOver &&
|
||||
SkCanvas::kFast_SrcRectConstraint == constraint);
|
||||
paint.getBlendMode() == SkBlendMode::kSrcOver);
|
||||
}
|
||||
|
||||
static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect* src,
|
||||
const SkRect* dst, GrAA aa, sk_sp<GrTextureProxy> proxy,
|
||||
const SkRect* dst, GrAA aa, SkCanvas::SrcRectConstraint constraint,
|
||||
sk_sp<GrTextureProxy> proxy,
|
||||
|
||||
SkColorSpace* colorSpace, const GrClip& clip, GrRenderTargetContext* rtc) {
|
||||
SkASSERT(!(SkToBool(src) && !SkToBool(dst)));
|
||||
SkRect srcRect = src ? *src : SkRect::MakeWH(proxy->width(), proxy->height());
|
||||
@ -129,7 +128,7 @@ static void draw_texture(const SkPaint& paint, const SkMatrix& ctm, const SkRect
|
||||
GrColor color = GrPixelConfigIsAlphaOnly(proxy->config())
|
||||
? SkColorToPremulGrColor(paint.getColor())
|
||||
: SkColorAlphaToGrColor(paint.getColor());
|
||||
rtc->drawTexture(clip, std::move(proxy), filter, color, srcRect, dstRect, aa, ctm,
|
||||
rtc->drawTexture(clip, std::move(proxy), filter, color, srcRect, dstRect, aa, constraint, ctm,
|
||||
std::move(csxf));
|
||||
}
|
||||
|
||||
@ -141,9 +140,9 @@ void SkGpuDevice::drawPinnedTextureProxy(sk_sp<GrTextureProxy> proxy, uint32_t p
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix, const SkPaint& paint) {
|
||||
GrAA aa = GrAA(paint.isAntiAlias());
|
||||
if (can_use_draw_texture(paint, aa, this->ctm(), constraint)) {
|
||||
draw_texture(paint, viewMatrix, srcRect, dstRect, aa, std::move(proxy), colorSpace,
|
||||
this->clip(), fRenderTargetContext.get());
|
||||
if (can_use_draw_texture(paint)) {
|
||||
draw_texture(paint, viewMatrix, srcRect, dstRect, aa, constraint, std::move(proxy),
|
||||
colorSpace, this->clip(), fRenderTargetContext.get());
|
||||
return;
|
||||
}
|
||||
GrTextureAdjuster adjuster(this->context(), std::move(proxy), alphaType, pinnedUniqueID,
|
||||
@ -156,7 +155,7 @@ void SkGpuDevice::drawTextureMaker(GrTextureMaker* maker, int imageW, int imageH
|
||||
SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix, const SkPaint& paint) {
|
||||
GrAA aa = GrAA(paint.isAntiAlias());
|
||||
if (can_use_draw_texture(paint, aa, viewMatrix, constraint)) {
|
||||
if (can_use_draw_texture(paint)) {
|
||||
sk_sp<SkColorSpace> cs;
|
||||
// We've done enough checks above to allow us to pass ClampNearest() and not check for
|
||||
// scaling adjustments.
|
||||
@ -166,8 +165,8 @@ void SkGpuDevice::drawTextureMaker(GrTextureMaker* maker, int imageW, int imageH
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
draw_texture(paint, viewMatrix, srcRect, dstRect, aa, std::move(proxy), cs.get(),
|
||||
this->clip(), fRenderTargetContext.get());
|
||||
draw_texture(paint, viewMatrix, srcRect, dstRect, aa, constraint, std::move(proxy),
|
||||
cs.get(), this->clip(), fRenderTargetContext.get());
|
||||
return;
|
||||
}
|
||||
this->drawTextureProducer(maker, srcRect, dstRect, constraint, viewMatrix, paint);
|
||||
|
@ -33,6 +33,8 @@ namespace {
|
||||
|
||||
enum class MultiTexture : bool { kNo = false, kYes = true };
|
||||
|
||||
enum class Domain : bool { kNo = false, kYes = true };
|
||||
|
||||
/**
|
||||
* Geometry Processor that draws a texture modulated by a vertex color (though, this is meant to be
|
||||
* the same value across all vertices of a quad and uses flat interpolation when available). This is
|
||||
@ -58,19 +60,30 @@ public:
|
||||
int fTextureIdx;
|
||||
};
|
||||
|
||||
template <typename Pos, MultiTexture MT, GrAA> struct OptionalAAVertex;
|
||||
template <typename Pos, MultiTexture MT, Domain D> struct OptionalDomainVertex;
|
||||
template <typename Pos, MultiTexture MT>
|
||||
struct OptionalAAVertex<Pos, MT, GrAA::kNo> : OptionalMultiTextureVertex<Pos, MT> {
|
||||
static constexpr GrAA kAA = GrAA::kNo;
|
||||
struct OptionalDomainVertex<Pos, MT, Domain::kNo> : OptionalMultiTextureVertex<Pos, MT> {
|
||||
static constexpr Domain kDomain = Domain::kNo;
|
||||
};
|
||||
template <typename Pos, MultiTexture MT>
|
||||
struct OptionalAAVertex<Pos, MT, GrAA::kYes> : OptionalMultiTextureVertex<Pos, MT> {
|
||||
struct OptionalDomainVertex<Pos, MT, Domain::kYes> : OptionalMultiTextureVertex<Pos, MT> {
|
||||
static constexpr Domain kDomain = Domain::kYes;
|
||||
SkRect fTextureDomain;
|
||||
};
|
||||
|
||||
template <typename Pos, MultiTexture MT, Domain D, GrAA> struct OptionalAAVertex;
|
||||
template <typename Pos, MultiTexture MT, Domain D>
|
||||
struct OptionalAAVertex<Pos, MT, D, GrAA::kNo> : OptionalDomainVertex<Pos, MT, D> {
|
||||
static constexpr GrAA kAA = GrAA::kNo;
|
||||
};
|
||||
template <typename Pos, MultiTexture MT, Domain D>
|
||||
struct OptionalAAVertex<Pos, MT, D, GrAA::kYes> : OptionalDomainVertex<Pos, MT, D> {
|
||||
static constexpr GrAA kAA = GrAA::kYes;
|
||||
SkPoint3 fEdges[4];
|
||||
};
|
||||
|
||||
template <typename Pos, MultiTexture MT, GrAA AA>
|
||||
using Vertex = OptionalAAVertex<Pos, MT, AA>;
|
||||
template <typename Pos, MultiTexture MT, Domain D, GrAA AA>
|
||||
using Vertex = OptionalAAVertex<Pos, MT, D, AA>;
|
||||
|
||||
// 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
|
||||
@ -87,7 +100,8 @@ public:
|
||||
|
||||
static sk_sp<GrGeometryProcessor> Make(sk_sp<GrTextureProxy> proxies[], int proxyCnt,
|
||||
sk_sp<GrColorSpaceXform> csxf, bool coverageAA,
|
||||
bool perspective, const GrSamplerState::Filter filters[],
|
||||
bool perspective, Domain domain,
|
||||
const GrSamplerState::Filter filters[],
|
||||
const GrShaderCaps& caps) {
|
||||
// We use placement new to avoid always allocating space for kMaxTextures TextureSampler
|
||||
// instances.
|
||||
@ -96,7 +110,7 @@ public:
|
||||
void* mem = GrGeometryProcessor::operator new(size);
|
||||
return sk_sp<TextureGeometryProcessor>(
|
||||
new (mem) TextureGeometryProcessor(proxies, proxyCnt, samplerCnt, std::move(csxf),
|
||||
coverageAA, perspective, filters, caps));
|
||||
coverageAA, perspective, domain, filters, caps));
|
||||
}
|
||||
|
||||
~TextureGeometryProcessor() override {
|
||||
@ -112,6 +126,7 @@ public:
|
||||
b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
|
||||
uint32_t x = this->usesCoverageEdgeAA() ? 0 : 1;
|
||||
x |= kFloat3_GrVertexAttribType == fPositions.fType ? 0 : 2;
|
||||
x |= fDomain.isInitialized() ? 4 : 0;
|
||||
b->add32(x);
|
||||
}
|
||||
|
||||
@ -150,6 +165,14 @@ public:
|
||||
args.fFragBuilder->codeAppend("float2 texCoord;");
|
||||
args.fVaryingHandler->addPassThroughAttribute(&textureGP.fTextureCoords,
|
||||
"texCoord");
|
||||
if (textureGP.fDomain.isInitialized()) {
|
||||
args.fFragBuilder->codeAppend("float4 domain;");
|
||||
args.fVaryingHandler->addPassThroughAttribute(
|
||||
&textureGP.fDomain, "domain",
|
||||
GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
|
||||
args.fFragBuilder->codeAppend(
|
||||
"texCoord = clamp(texCoord, domain.xy, domain.zw);");
|
||||
}
|
||||
if (textureGP.numTextureSamplers() > 1) {
|
||||
// If this changes to float, reconsider Interpolation::kMustBeFlat.
|
||||
SkASSERT(kInt_GrVertexAttribType == textureGP.fTextureIdx.fType);
|
||||
@ -275,7 +298,8 @@ private:
|
||||
|
||||
TextureGeometryProcessor(sk_sp<GrTextureProxy> proxies[], int proxyCnt, int samplerCnt,
|
||||
sk_sp<GrColorSpaceXform> csxf, bool coverageAA, bool perspective,
|
||||
const GrSamplerState::Filter filters[], const GrShaderCaps& caps)
|
||||
Domain domain, const GrSamplerState::Filter filters[],
|
||||
const GrShaderCaps& caps)
|
||||
: INHERITED(kTextureGeometryProcessor_ClassID), fColorSpaceXform(std::move(csxf)) {
|
||||
SkASSERT(proxyCnt > 0 && samplerCnt >= proxyCnt);
|
||||
fSamplers[0].reset(std::move(proxies[0]), filters[0]);
|
||||
@ -306,7 +330,9 @@ private:
|
||||
SkASSERT(caps.integerSupport());
|
||||
fTextureIdx = this->addVertexAttrib("textureIdx", kInt_GrVertexAttribType);
|
||||
}
|
||||
|
||||
if (domain == Domain::kYes) {
|
||||
fDomain = this->addVertexAttrib("domain", kFloat4_GrVertexAttribType);
|
||||
}
|
||||
if (coverageAA) {
|
||||
fAAEdges[0] = this->addVertexAttrib("aaEdge0", kFloat3_GrVertexAttribType);
|
||||
fAAEdges[1] = this->addVertexAttrib("aaEdge1", kFloat3_GrVertexAttribType);
|
||||
@ -319,6 +345,7 @@ private:
|
||||
Attribute fColors;
|
||||
Attribute fTextureCoords;
|
||||
Attribute fTextureIdx;
|
||||
Attribute fDomain;
|
||||
Attribute fAAEdges[4];
|
||||
sk_sp<GrColorSpaceXform> fColorSpaceXform;
|
||||
TextureSampler fSamplers[1];
|
||||
@ -509,12 +536,52 @@ template <typename V> struct TexIdAssigner<V, MultiTexture::kYes> {
|
||||
template <typename V> struct TexIdAssigner<V, MultiTexture::kNo> {
|
||||
static void Assign(V* vertices, int textureIdx) {}
|
||||
};
|
||||
|
||||
template <typename V, Domain D = V::kDomain> struct DomainAssigner;
|
||||
|
||||
template <typename V> struct DomainAssigner<V, Domain::kYes> {
|
||||
static void Assign(V* vertices, Domain domain, GrSamplerState::Filter filter,
|
||||
const SkRect& srcRect, GrSurfaceOrigin origin, float iw, float ih) {
|
||||
static constexpr SkRect kLargeRect = {-2, -2, 2, 2};
|
||||
SkRect domainRect;
|
||||
if (domain == Domain::kYes) {
|
||||
auto ltrb = Sk4f::Load(&srcRect);
|
||||
if (filter == GrSamplerState::Filter::kBilerp) {
|
||||
auto rblt = SkNx_shuffle<2, 3, 0, 1>(ltrb);
|
||||
auto whwh = (rblt - ltrb).abs();
|
||||
auto c = (rblt + ltrb) * 0.5f;
|
||||
static const Sk4f kOffsets = {0.5f, 0.5f, -0.5f, -0.5f};
|
||||
ltrb = (whwh < 1.f).thenElse(c, ltrb + kOffsets);
|
||||
}
|
||||
ltrb *= Sk4f(iw, ih, iw, ih);
|
||||
if (origin == kBottomLeft_GrSurfaceOrigin) {
|
||||
static const Sk4f kMul = {1.f, -1.f, 1.f, -1.f};
|
||||
static const Sk4f kAdd = {0.f, 1.f, 0.f, 1.f};
|
||||
ltrb = SkNx_shuffle<0, 3, 2, 1>(kMul * ltrb + kAdd);
|
||||
}
|
||||
ltrb.store(&domainRect);
|
||||
} else {
|
||||
domainRect = kLargeRect;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vertices[i].fTextureDomain = domainRect;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename V> struct DomainAssigner<V, Domain::kNo> {
|
||||
static void Assign(V*, Domain domain, GrSamplerState::Filter, const SkRect&, GrSurfaceOrigin,
|
||||
float iw, float ih) {
|
||||
SkASSERT(domain == Domain::kNo);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
template <typename V>
|
||||
static void tessellate_quad(const GrPerspQuad& devQuad, const SkRect& srcRect, GrColor color,
|
||||
GrSurfaceOrigin origin, V* vertices, SkScalar iw, SkScalar ih,
|
||||
int textureIdx) {
|
||||
GrSurfaceOrigin origin, GrSamplerState::Filter filter, V* vertices,
|
||||
SkScalar iw, SkScalar ih, int textureIdx, Domain domain) {
|
||||
SkRect texRect = {
|
||||
iw * srcRect.fLeft,
|
||||
ih * srcRect.fTop,
|
||||
@ -531,6 +598,7 @@ static void tessellate_quad(const GrPerspQuad& devQuad, const SkRect& srcRect, G
|
||||
vertices[2].fColor = color;
|
||||
vertices[3].fColor = color;
|
||||
TexIdAssigner<V>::Assign(vertices, textureIdx);
|
||||
DomainAssigner<V>::Assign(vertices, domain, filter, srcRect, origin, iw, ih);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -542,11 +610,12 @@ public:
|
||||
static std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy,
|
||||
GrSamplerState::Filter filter, GrColor color,
|
||||
const SkRect& srcRect, const SkRect& dstRect,
|
||||
GrAAType aaType, const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> csxf, bool allowSRBInputs) {
|
||||
GrAAType aaType, SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf,
|
||||
bool allowSRBInputs) {
|
||||
return std::unique_ptr<GrDrawOp>(new TextureOp(std::move(proxy), filter, color, srcRect,
|
||||
dstRect, aaType, viewMatrix, std::move(csxf),
|
||||
allowSRBInputs));
|
||||
dstRect, aaType, constraint, viewMatrix,
|
||||
std::move(csxf), allowSRBInputs));
|
||||
}
|
||||
|
||||
~TextureOp() override {
|
||||
@ -587,11 +656,11 @@ public:
|
||||
str.appendf(
|
||||
"%d: Color: 0x%08x, ProxyIdx: %d, TexRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f] "
|
||||
"Quad [(%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f), (%.2f, %.2f)]\n",
|
||||
i, draw.fColor, draw.fTextureIdx, draw.fSrcRect.fLeft, draw.fSrcRect.fTop,
|
||||
draw.fSrcRect.fRight, draw.fSrcRect.fBottom, draw.fQuad.point(0).fX,
|
||||
draw.fQuad.point(0).fY, draw.fQuad.point(1).fX, draw.fQuad.point(1).fY,
|
||||
draw.fQuad.point(2).fX, draw.fQuad.point(2).fY, draw.fQuad.point(3).fX,
|
||||
draw.fQuad.point(3).fY);
|
||||
i, draw.color(), draw.textureIdx(), draw.srcRect().fLeft, draw.srcRect().fTop,
|
||||
draw.srcRect().fRight, draw.srcRect().fBottom, draw.quad().point(0).fX,
|
||||
draw.quad().point(0).fY, draw.quad().point(1).fX, draw.quad().point(1).fY,
|
||||
draw.quad().point(2).fX, draw.quad().point(2).fY, draw.quad().point(3).fX,
|
||||
draw.quad().point(3).fY);
|
||||
}
|
||||
str += INHERITED::dumpInfo();
|
||||
return str;
|
||||
@ -629,7 +698,8 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
|
||||
TextureOp(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter, GrColor color,
|
||||
const SkRect& srcRect, const SkRect& dstRect, GrAAType aaType,
|
||||
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf, bool allowSRGBInputs)
|
||||
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> csxf, bool allowSRGBInputs)
|
||||
: INHERITED(ClassID())
|
||||
, fColorSpaceXform(std::move(csxf))
|
||||
, fProxy0(proxy.release())
|
||||
@ -639,29 +709,36 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
, fFinalized(0)
|
||||
, fAllowSRGBInputs(allowSRGBInputs ? 1 : 0) {
|
||||
SkASSERT(aaType != GrAAType::kMixedSamples);
|
||||
Draw& draw = fDraws.push_back();
|
||||
draw.fSrcRect = srcRect;
|
||||
draw.fTextureIdx = 0;
|
||||
draw.fColor = color;
|
||||
// No need to use a texture domain with nearest filtering unless there is AA bloating.
|
||||
if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
|
||||
filter == GrSamplerState::Filter::kNearest && GrAAType::kCoverage != aaType) {
|
||||
constraint = SkCanvas::kFast_SrcRectConstraint;
|
||||
}
|
||||
|
||||
const Draw& draw = fDraws.emplace_back(srcRect, 0, GrPerspQuad(dstRect, viewMatrix),
|
||||
constraint, color);
|
||||
fPerspective = viewMatrix.hasPerspective();
|
||||
fDomain = (bool)draw.domain();
|
||||
SkRect bounds;
|
||||
draw.fQuad = GrPerspQuad(dstRect, viewMatrix);
|
||||
bounds = draw.fQuad.bounds();
|
||||
bounds = draw.quad().bounds();
|
||||
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
|
||||
|
||||
fMaxApproxDstPixelArea = RectSizeAsSizeT(bounds);
|
||||
}
|
||||
|
||||
template <typename Pos, MultiTexture MT, GrAA AA>
|
||||
template <typename Pos, MultiTexture MT, Domain D, GrAA AA>
|
||||
void tess(void* v, const float iw[], const float ih[], const GrGeometryProcessor* gp) {
|
||||
using Vertex = TextureGeometryProcessor::Vertex<Pos, MT, AA>;
|
||||
using Vertex = TextureGeometryProcessor::Vertex<Pos, MT, D, AA>;
|
||||
SkASSERT(gp->getVertexStride() == sizeof(Vertex));
|
||||
auto vertices = static_cast<Vertex*>(v);
|
||||
auto proxies = this->proxies();
|
||||
auto filters = this->filters();
|
||||
for (const auto& draw : fDraws) {
|
||||
auto origin = proxies[draw.fTextureIdx]->origin();
|
||||
tessellate_quad<Vertex>(draw.fQuad, draw.fSrcRect, draw.fColor, origin, vertices,
|
||||
iw[draw.fTextureIdx], ih[draw.fTextureIdx], draw.fTextureIdx);
|
||||
auto textureIdx = draw.textureIdx();
|
||||
auto origin = proxies[textureIdx]->origin();
|
||||
tessellate_quad<Vertex>(draw.quad(), draw.srcRect(), draw.color(), origin,
|
||||
filters[textureIdx], vertices, iw[textureIdx], ih[textureIdx],
|
||||
textureIdx, draw.domain());
|
||||
vertices += 4;
|
||||
}
|
||||
}
|
||||
@ -677,10 +754,11 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
proxiesSPs[i] = sk_ref_sp(proxies[i]);
|
||||
}
|
||||
|
||||
Domain domain = fDomain ? Domain::kYes : Domain::kNo;
|
||||
bool coverageAA = GrAAType::kCoverage == this->aaType();
|
||||
sk_sp<GrGeometryProcessor> gp = TextureGeometryProcessor::Make(
|
||||
proxiesSPs, fProxyCnt, std::move(fColorSpaceXform), coverageAA, fPerspective,
|
||||
filters, *target->caps().shaderCaps());
|
||||
domain, filters, *target->caps().shaderCaps());
|
||||
GrPipeline::InitArgs args;
|
||||
args.fProxy = target->proxy();
|
||||
args.fCaps = &target->caps();
|
||||
@ -712,35 +790,33 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
ih[t] = 1.f / texture->height();
|
||||
}
|
||||
|
||||
if (fPerspective) {
|
||||
if (fProxyCnt > 1) {
|
||||
if (coverageAA) {
|
||||
this->tess<SkPoint3, MultiTexture::kYes, GrAA::kYes>(vdata, iw, ih, gp.get());
|
||||
} else {
|
||||
this->tess<SkPoint3, MultiTexture::kYes, GrAA::kNo>(vdata, iw, ih, gp.get());
|
||||
}
|
||||
} else {
|
||||
if (coverageAA) {
|
||||
this->tess<SkPoint3, MultiTexture::kNo, GrAA::kYes>(vdata, iw, ih, gp.get());
|
||||
} else {
|
||||
this->tess<SkPoint3, MultiTexture::kNo, GrAA::kNo>(vdata, iw, ih, gp.get());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fProxyCnt > 1) {
|
||||
if (coverageAA) {
|
||||
this->tess<SkPoint, MultiTexture::kYes, GrAA::kYes>(vdata, iw, ih, gp.get());
|
||||
} else {
|
||||
this->tess<SkPoint, MultiTexture::kYes, GrAA::kNo>(vdata, iw, ih, gp.get());
|
||||
}
|
||||
} else {
|
||||
if (coverageAA) {
|
||||
this->tess<SkPoint, MultiTexture::kNo, GrAA::kYes>(vdata, iw, ih, gp.get());
|
||||
} else {
|
||||
this->tess<SkPoint, MultiTexture::kNo, GrAA::kNo>(vdata, iw, ih, gp.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
using TessFn =
|
||||
decltype(&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kNo>);
|
||||
static constexpr TessFn kTessFns[] = {
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kNo, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kYes, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kNo, Domain::kYes, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kYes, Domain::kNo, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kYes, Domain::kNo, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kYes, Domain::kYes, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint, MultiTexture::kYes, Domain::kYes, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kNo, Domain::kNo, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kNo, Domain::kNo, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kNo, Domain::kYes, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kNo, Domain::kYes, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kYes, Domain::kNo, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kYes, Domain::kNo, GrAA::kYes>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kYes, Domain::kYes, GrAA::kNo>,
|
||||
&TextureOp::tess<SkPoint3, MultiTexture::kYes, Domain::kYes, GrAA::kYes>,
|
||||
};
|
||||
int tessFnIdx = 0;
|
||||
tessFnIdx |= coverageAA ? 0x1 : 0x0;
|
||||
tessFnIdx |= fDomain ? 0x2 : 0x0;
|
||||
tessFnIdx |= (fProxyCnt > 1) ? 0x4 : 0x0;
|
||||
tessFnIdx |= fPerspective ? 0x8 : 0x0;
|
||||
(this->*(kTessFns[tessFnIdx]))(vdata, iw, ih, gp.get());
|
||||
|
||||
GrPrimitiveType primitiveType =
|
||||
fDraws.count() > 1 ? GrPrimitiveType::kTriangles : GrPrimitiveType::kTriangleStrip;
|
||||
GrMesh mesh(primitiveType);
|
||||
@ -806,7 +882,7 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
int firstNewDraw = fDraws.count();
|
||||
fDraws.push_back_n(that->fDraws.count(), that->fDraws.begin());
|
||||
for (int i = firstNewDraw; i < fDraws.count(); ++i) {
|
||||
fDraws[i].fTextureIdx = map[fDraws[i].fTextureIdx];
|
||||
fDraws[i].setTextureIdx(map[fDraws[i].textureIdx()]);
|
||||
}
|
||||
} else {
|
||||
// We can get here when one of the ops is already multitextured but the other cannot
|
||||
@ -822,6 +898,7 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
this->joinBounds(*that);
|
||||
fMaxApproxDstPixelArea = SkTMax(that->fMaxApproxDstPixelArea, fMaxApproxDstPixelArea);
|
||||
fPerspective |= that->fPerspective;
|
||||
fDomain |= that->fDomain;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -894,9 +971,26 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
return &fFilter0;
|
||||
}
|
||||
|
||||
struct Draw {
|
||||
class Draw {
|
||||
public:
|
||||
Draw(const SkRect& srcRect, int textureIdx, const GrPerspQuad& quad,
|
||||
SkCanvas::SrcRectConstraint constraint, GrColor color)
|
||||
: fSrcRect(srcRect)
|
||||
, fHasDomain(constraint == SkCanvas::kStrict_SrcRectConstraint)
|
||||
, fTextureIdx(SkToUInt(textureIdx))
|
||||
, fQuad(quad)
|
||||
, fColor(color) {}
|
||||
const GrPerspQuad& quad() const { return fQuad; }
|
||||
int textureIdx() const { return SkToInt(fTextureIdx); }
|
||||
const SkRect& srcRect() const { return fSrcRect; }
|
||||
GrColor color() const { return fColor; }
|
||||
Domain domain() const { return Domain(fHasDomain); }
|
||||
void setTextureIdx(int i) { fTextureIdx = SkToUInt(i); }
|
||||
|
||||
private:
|
||||
SkRect fSrcRect;
|
||||
int fTextureIdx;
|
||||
unsigned fHasDomain : 1;
|
||||
unsigned fTextureIdx : 31;
|
||||
GrPerspQuad fQuad;
|
||||
GrColor fColor;
|
||||
};
|
||||
@ -914,6 +1008,7 @@ __attribute__((no_sanitize("float-cast-overflow")))
|
||||
uint8_t fProxyCnt;
|
||||
unsigned fAAType : 2;
|
||||
unsigned fPerspective : 1;
|
||||
unsigned fDomain : 1;
|
||||
// Used to track whether fProxy is ref'ed or has a pending IO after finalize() is called.
|
||||
unsigned fFinalized : 1;
|
||||
unsigned fAllowSRGBInputs : 1;
|
||||
@ -930,10 +1025,11 @@ namespace GrTextureOp {
|
||||
|
||||
std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy> proxy, GrSamplerState::Filter filter,
|
||||
GrColor color, const SkRect& srcRect, const SkRect& dstRect,
|
||||
GrAAType aaType, const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform> csxf, bool allowSRGBInputs) {
|
||||
return TextureOp::Make(std::move(proxy), filter, color, srcRect, dstRect, aaType, viewMatrix,
|
||||
std::move(csxf), allowSRGBInputs);
|
||||
GrAAType aaType, SkCanvas::SrcRectConstraint constraint,
|
||||
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform> csxf,
|
||||
bool allowSRGBInputs) {
|
||||
return TextureOp::Make(std::move(proxy), filter, color, srcRect, dstRect, aaType, constraint,
|
||||
viewMatrix, std::move(csxf), allowSRGBInputs);
|
||||
}
|
||||
|
||||
} // namespace GrTextureOp
|
||||
@ -970,8 +1066,10 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) {
|
||||
if (random->nextBool()) {
|
||||
aaType = (fsaaType == GrFSAAType::kUnifiedMSAA) ? GrAAType::kMSAA : GrAAType::kCoverage;
|
||||
}
|
||||
return GrTextureOp::Make(std::move(proxy), filter, color, srcRect, rect, aaType, viewMatrix,
|
||||
std::move(csxf), allowSRGBInputs);
|
||||
auto constraint = random->nextBool() ? SkCanvas::kStrict_SrcRectConstraint
|
||||
: SkCanvas::kFast_SrcRectConstraint;
|
||||
return GrTextureOp::Make(std::move(proxy), filter, color, srcRect, rect, aaType, constraint,
|
||||
viewMatrix, std::move(csxf), allowSRGBInputs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "GrColor.h"
|
||||
#include "GrSamplerState.h"
|
||||
#include "GrTypesPriv.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
class GrColorSpaceXform;
|
||||
@ -17,6 +18,7 @@ struct SkRect;
|
||||
class SkMatrix;
|
||||
|
||||
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
|
||||
@ -25,6 +27,6 @@ namespace GrTextureOp {
|
||||
*/
|
||||
std::unique_ptr<GrDrawOp> Make(sk_sp<GrTextureProxy>, GrSamplerState::Filter, GrColor,
|
||||
const SkRect& srcRect, const SkRect& dstRect, GrAAType,
|
||||
const SkMatrix& viewMatrix, sk_sp<GrColorSpaceXform>,
|
||||
bool allowSRGBInputs);
|
||||
SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
|
||||
sk_sp<GrColorSpaceXform>, bool allowSRGBInputs);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user