diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index a6ba1ea863e15..a6141c6951fda 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -610,7 +610,7 @@ void GrRenderTargetContext::drawFilledQuad(const GrClip& clip, } void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip, - sk_sp proxy, + GrSurfaceProxyView proxyView, GrColorType srcColorType, sk_sp textureXform, GrSamplerState::Filter filter, @@ -624,7 +624,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip, ASSERT_SINGLE_OWNER RETURN_IF_ABANDONED SkDEBUGCODE(this->validate();) - SkASSERT(proxy); + SkASSERT(proxyView.asTextureProxy()); GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexturedQuad", fContext); AutoCheckFlush acf(this->drawingManager()); @@ -648,7 +648,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip, // Use the provided domain, although hypothetically we could detect that the cropped local // quad is sufficiently inside the domain and the constraint could be dropped. this->addDrawOp(finalClip, - GrTextureOp::Make(fContext, std::move(proxy), srcColorType, + GrTextureOp::Make(fContext, std::move(proxyView), srcColorType, std::move(textureXform), filter, color, saturate, blendMode, aaType, edgeFlags, croppedDeviceQuad, croppedLocalQuad, domain)); @@ -898,9 +898,9 @@ void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetE const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint ? &set[i].fSrcRect : nullptr; - this->drawTexturedQuad(clip, set[i].fProxy, set[i].fSrcColorType, texXform, filter, - {alpha, alpha, alpha, alpha}, mode, aa, set[i].fAAFlags, - quad, srcQuad, domain); + this->drawTexturedQuad(clip, set[i].fProxyView, set[i].fSrcColorType, texXform, filter, + {alpha, alpha, alpha, alpha}, mode, aa, set[i].fAAFlags, quad, + srcQuad, domain); } } else { // Can use a single op, avoiding GrPaint creation, and can batch across proxies diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index 286bff57899bd..19d240a367fe3 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -202,9 +202,12 @@ class GrRenderTargetContext : public GrSurfaceContext { sk_sp texXform) { const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr; - this->drawTexturedQuad(clip, std::move(proxy), srcColorType, std::move(texXform), filter, - color, mode, aa, edgeAA, GrQuad::MakeFromRect(dstRect, viewMatrix), - GrQuad(srcRect), domain); + GrSurfaceOrigin origin = proxy->origin(); + const GrSwizzle& swizzle = proxy->textureSwizzle(); + GrSurfaceProxyView proxyView(std::move(proxy), origin, swizzle); + this->drawTexturedQuad(clip, std::move(proxyView), srcColorType, std::move(texXform), + filter, color, mode, aa, edgeAA, + GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), domain); } /** @@ -218,14 +221,18 @@ class GrRenderTargetContext : public GrSurfaceContext { const SkPoint srcQuad[4], const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA, const SkRect* domain, const SkMatrix& viewMatrix, sk_sp texXform) { - this->drawTexturedQuad(clip, std::move(proxy), srcColorType, std::move(texXform), filter, - color, mode, aa, edgeAA, GrQuad::MakeFromSkQuad(dstQuad, viewMatrix), + GrSurfaceOrigin origin = proxy->origin(); + const GrSwizzle& swizzle = proxy->textureSwizzle(); + GrSurfaceProxyView proxyView(std::move(proxy), origin, swizzle); + this->drawTexturedQuad(clip, std::move(proxyView), srcColorType, std::move(texXform), + filter, color, mode, aa, edgeAA, + GrQuad::MakeFromSkQuad(dstQuad, viewMatrix), GrQuad::MakeFromSkQuad(srcQuad, SkMatrix::I()), domain); } /** Used with drawTextureSet */ struct TextureSetEntry { - sk_sp fProxy; + GrSurfaceProxyView fProxyView; GrColorType fSrcColorType; SkRect fSrcRect; SkRect fDstRect; @@ -601,7 +608,7 @@ class GrRenderTargetContext : public GrSurfaceContext { // Like drawFilledQuad but does not require using a GrPaint or FP for texturing void drawTexturedQuad(const GrClip& clip, - sk_sp proxy, + GrSurfaceProxyView proxyView, GrColorType srcColorType, sk_sp textureXform, GrSamplerState::Filter filter, diff --git a/src/gpu/GrSurfaceProxyView.h b/src/gpu/GrSurfaceProxyView.h index 1649e12c79201..419c11760b961 100644 --- a/src/gpu/GrSurfaceProxyView.h +++ b/src/gpu/GrSurfaceProxyView.h @@ -25,16 +25,16 @@ class GrSurfaceProxyView { : fProxy(proxy), fOrigin(kTopLeft_GrSurfaceOrigin) {} GrSurfaceProxyView(GrSurfaceProxyView&& view) = default; - GrSurfaceProxyView(const GrSurfaceProxyView&) = delete; + GrSurfaceProxyView(const GrSurfaceProxyView&) = default; - GrSurfaceProxyView& operator=(const GrSurfaceProxyView& that) = default; + GrSurfaceProxyView& operator=(const GrSurfaceProxyView&) = default; - bool operator==(const GrSurfaceProxyView& view) { - return fProxy.get() == view.fProxy.get() && + bool operator==(const GrSurfaceProxyView& view) const { + return fProxy->uniqueID() == view.fProxy->uniqueID() && fOrigin == view.fOrigin && fSwizzle == view.fSwizzle; } - bool operator!=(const GrSurfaceProxyView& other) { return !(*this == other); } + bool operator!=(const GrSurfaceProxyView& other) const { return !(*this == other); } GrSurfaceProxy* proxy() const { return fProxy.get(); } GrTextureProxy* asTextureProxy() const { return fProxy->asTextureProxy(); } diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp index 1179a8fd019bd..ce5c49bd9ea90 100644 --- a/src/gpu/SkGpuDevice_drawTexture.cpp +++ b/src/gpu/SkGpuDevice_drawTexture.cpp @@ -551,7 +551,10 @@ void SkGpuDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int co continue; } - textures[i].fProxy = std::move(proxy); + // TODO: have refPinnedTextureProxy and asTextureProxyRef return GrSurfaceProxyViews. + GrSurfaceOrigin origin = proxy->origin(); + const GrSwizzle& swizzle = proxy->textureSwizzle(); + textures[i].fProxyView = {std::move(proxy), origin, swizzle}; textures[i].fSrcColorType = SkColorTypeToGrColorType(image->colorType()); textures[i].fSrcRect = set[i].fSrcRect; textures[i].fDstRect = set[i].fDstRect; @@ -562,8 +565,9 @@ void SkGpuDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int co textures[i].fAAFlags = SkToGrQuadAAFlags(set[i].fAAFlags); if (n > 0 && - (!GrTextureProxy::ProxiesAreCompatibleAsDynamicState(textures[i].fProxy.get(), - textures[base].fProxy.get()) || + (!GrTextureProxy::ProxiesAreCompatibleAsDynamicState( + textures[i].fProxyView.asTextureProxy(), + textures[base].fProxyView.asTextureProxy()) || set[i].fImage->alphaType() != set[base].fImage->alphaType() || !SkColorSpace::Equals(set[i].fImage->colorSpace(), set[base].fImage->colorSpace()))) { draw(); diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp index e4a287c000225..7f5c593e75d44 100644 --- a/src/gpu/ops/GrTextureOp.cpp +++ b/src/gpu/ops/GrTextureOp.cpp @@ -144,7 +144,7 @@ static void compute_src_quad(GrSurfaceOrigin origin, const GrQuad& srcQuad, class TextureOp final : public GrMeshDrawOp { public: static std::unique_ptr Make(GrRecordingContext* context, - sk_sp proxy, + GrSurfaceProxyView proxyView, sk_sp textureXform, GrSamplerState::Filter filter, const SkPMColor4f& color, @@ -155,8 +155,9 @@ class TextureOp final : public GrMeshDrawOp { const GrQuad& localQuad, const SkRect* domain) { GrOpMemoryPool* pool = context->priv().opMemoryPool(); - return pool->allocate(std::move(proxy), std::move(textureXform), filter, color, - saturate, aaType, aaFlags, deviceQuad, localQuad, domain); + return pool->allocate(std::move(proxyView), std::move(textureXform), filter, + color, saturate, aaType, aaFlags, deviceQuad, localQuad, + domain); } static std::unique_ptr Make(GrRecordingContext* context, const GrRenderTargetContext::TextureSetEntry set[], @@ -167,7 +168,7 @@ class TextureOp final : public GrMeshDrawOp { SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix, sk_sp textureColorSpaceXform) { - size_t size = sizeof(TextureOp) + sizeof(ProxyCountPair) * (cnt - 1); + size_t size = sizeof(TextureOp) + sizeof(ViewCountPair) * (cnt - 1); GrOpMemoryPool* pool = context->priv().opMemoryPool(); void* mem = pool->allocate(size); return std::unique_ptr(new (mem) TextureOp(set, cnt, filter, saturate, aaType, @@ -176,8 +177,8 @@ class TextureOp final : public GrMeshDrawOp { } ~TextureOp() override { - for (unsigned p = 0; p < fProxyCnt; ++p) { - fProxyCountPairs[p].fProxy->unref(); + for (unsigned p = 1; p < fProxyCnt; ++p) { + fViewCountPairs[p].~ViewCountPair(); } } @@ -186,7 +187,7 @@ class TextureOp final : public GrMeshDrawOp { void visitProxies(const VisitProxyFunc& func) const override { for (unsigned p = 0; p < fProxyCnt; ++p) { bool mipped = (GrSamplerState::Filter::kMipMap == this->filter()); - func(fProxyCountPairs[p].fProxy, GrMipMapped(mipped)); + func(fViewCountPairs[p].fProxyView.asTextureProxy(), GrMipMapped(mipped)); } } @@ -197,10 +198,10 @@ class TextureOp final : public GrMeshDrawOp { auto iter = fQuads.iterator(); for (unsigned p = 0; p < fProxyCnt; ++p) { str.appendf("Proxy ID: %d, Filter: %d\n", - fProxyCountPairs[p].fProxy->uniqueID().asUInt(), + fViewCountPairs[p].fProxyView.proxy()->uniqueID().asUInt(), static_cast(fFilter)); int i = 0; - while(i < fProxyCountPairs[p].fQuadCnt && iter.next()) { + while(i < fViewCountPairs[p].fQuadCnt && iter.next()) { const GrQuad& quad = iter.deviceQuad(); const GrQuad& uv = iter.localQuad(); const ColorDomainAndAA& info = iter.metadata(); @@ -262,8 +263,8 @@ class TextureOp final : public GrMeshDrawOp { Domain domain() const { return Domain(fHasDomain); } GrQuadAAFlags aaFlags() const { return static_cast(fAAFlags); } }; - struct ProxyCountPair { - GrTextureProxy* fProxy; + struct ViewCountPair { + GrSurfaceProxyView fProxyView; int fQuadCnt; }; @@ -336,7 +337,7 @@ class TextureOp final : public GrMeshDrawOp { // 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 proxy, + TextureOp(GrSurfaceProxyView proxyView, sk_sp textureColorSpaceXform, GrSamplerState::Filter filter, const SkPMColor4f& color, @@ -358,7 +359,8 @@ class TextureOp final : public GrMeshDrawOp { fAAType = static_cast(aaType); // We expect our caller to have already caught this optimization. - SkASSERT(!domainRect || !domainRect->contains(proxy->backingStoreBoundsRect())); + SkASSERT(!domainRect || + !domainRect->contains(proxyView.proxy()->backingStoreBoundsRect())); // We may have had a strict constraint with nearest filter solely due to possible AA bloat. // If we don't have (or determined we don't need) coverage AA then we can skip using a @@ -371,7 +373,7 @@ class TextureOp final : public GrMeshDrawOp { fQuads.append(dstQuad, {color, domainRect, aaFlags}, &srcQuad); fProxyCnt = 1; - fProxyCountPairs[0] = {proxy.release(), 1}; + fViewCountPairs[0] = {std::move(proxyView), 1}; fTotNumQuads = 1; this->setBounds(dstQuad.bounds(), HasAABloat(aaType == GrAAType::kCoverage), IsHairline::kNo); @@ -399,12 +401,23 @@ class TextureOp final : public GrMeshDrawOp { bool allOpaque = true; Domain netDomain = Domain::kNo; GrTextureProxy* curProxy = nullptr; + for (unsigned p = 0; p < fProxyCnt; ++p) { - fProxyCountPairs[p].fProxy = curProxy = SkRef(set[p].fProxy.get()); - fProxyCountPairs[p].fQuadCnt = 1; + if (p == 0) { + // We do not placement new the first ViewCountPair since that one is allocated and + // initialized as part of the GrTextureOp creation. + fViewCountPairs[p].fProxyView = std::move(set[p].fProxyView); + fViewCountPairs[p].fQuadCnt = 1; + } else { + // We must placement new the ViewCountPairs here so that the sk_sps in the + // GrSurfaceProxyView get initialized properly. + new(&fViewCountPairs[p])ViewCountPair({std::move(set[p].fProxyView), 1}); + } fTotNumQuads += 1; - SkASSERT(curProxy->textureType() == fProxyCountPairs[0].fProxy->textureType()); - SkASSERT(curProxy->config() == fProxyCountPairs[0].fProxy->config()); + curProxy = fViewCountPairs[p].fProxyView.asTextureProxy(); + SkASSERT(curProxy->textureType() == + fViewCountPairs[0].fProxyView.asTextureProxy()->textureType()); + SkASSERT(curProxy->config() == fViewCountPairs[0].fProxyView.proxy()->config()); SkMatrix ctm = viewMatrix; if (set[p].fPreViewMatrix) { @@ -536,9 +549,9 @@ class TextureOp final : public GrMeshDrawOp { for (const auto& op : ChainRange(texOp)) { auto iter = op.fQuads.iterator(); for (unsigned p = 0; p < op.fProxyCnt; ++p) { - GrTextureProxy* proxy = op.fProxyCountPairs[p].fProxy; + GrTextureProxy* proxy = op.fViewCountPairs[p].fProxyView.asTextureProxy(); - int quadCnt = op.fProxyCountPairs[p].fQuadCnt; + int quadCnt = op.fViewCountPairs[p].fQuadCnt; SkDEBUGCODE(totQuadsSeen += quadCnt;) int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad(); @@ -583,16 +596,16 @@ class TextureOp final : public GrMeshDrawOp { #ifdef SK_DEBUG void validate() const override { - auto textureType = fProxyCountPairs[0].fProxy->textureType(); - const GrSwizzle& swizzle = fProxyCountPairs[0].fProxy->textureSwizzle(); + auto textureType = fViewCountPairs[0].fProxyView.asTextureProxy()->textureType(); GrAAType aaType = this->aaType(); for (const auto& op : ChainRange(this)) { for (unsigned p = 0; p < op.fProxyCnt; ++p) { - auto* proxy = op.fProxyCountPairs[p].fProxy; + auto* proxy = op.fViewCountPairs[p].fProxyView.asTextureProxy(); SkASSERT(proxy); SkASSERT(proxy->textureType() == textureType); - SkASSERT(proxy->textureSwizzle() == swizzle); + SkASSERT(op.fViewCountPairs[p].fProxyView.swizzle() == + fViewCountPairs[0].fProxyView.swizzle()); } // Each individual op must be a single aaType. kCoverage and kNone ops can chain @@ -631,7 +644,7 @@ class TextureOp final : public GrMeshDrawOp { desc->fNumProxies += op.fProxyCnt; for (unsigned p = 0; p < op.fProxyCnt; ++p) { - maxQuadsPerMesh = SkTMax(op.fProxyCountPairs[p].fQuadCnt, maxQuadsPerMesh); + maxQuadsPerMesh = SkTMax(op.fViewCountPairs[p].fQuadCnt, maxQuadsPerMesh); } desc->fNumTotalQuads += op.totNumQuads(); @@ -656,7 +669,7 @@ class TextureOp final : public GrMeshDrawOp { #ifdef SK_DEBUG int tmp = 0; for (unsigned p = 0; p < fProxyCnt; ++p) { - tmp += fProxyCountPairs[p].fQuadCnt; + tmp += fViewCountPairs[p].fQuadCnt; } SkASSERT(tmp == fTotNumQuads); #endif @@ -732,8 +745,9 @@ class TextureOp final : public GrMeshDrawOp { sk_sp gp; { - const GrBackendFormat& backendFormat = fProxyCountPairs[0].fProxy->backendFormat(); - const GrSwizzle& swizzle = fProxyCountPairs[0].fProxy->textureSwizzle(); + const GrBackendFormat& backendFormat = + fViewCountPairs[0].fProxyView.proxy()->backendFormat(); + const GrSwizzle& swizzle = fViewCountPairs[0].fProxyView.swizzle(); GrSamplerState samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, this->filter()); @@ -804,13 +818,16 @@ class TextureOp final : public GrMeshDrawOp { if (fFilter != that->fFilter) { return CombineResult::kCannotCombine; } - auto thisProxy = fProxyCountPairs[0].fProxy; - auto thatProxy = that->fProxyCountPairs[0].fProxy; - if (fProxyCnt > 1 || that->fProxyCnt > 1 || - thisProxy->uniqueID() != thatProxy->uniqueID()) { + const auto& thisView = fViewCountPairs[0].fProxyView; + const auto& thatView = that->fViewCountPairs[0].fProxyView; + auto thisProxy = thisView.asTextureProxy(); + auto thatProxy = thatView.asTextureProxy(); + if (fProxyCnt > 1 || that->fProxyCnt > 1 || thisView != thatView) { // We can't merge across different proxies. Check if 'this' can be chained with 'that'. if (GrTextureProxy::ProxiesAreCompatibleAsDynamicState(thisProxy, thatProxy) && - caps.dynamicStateArrayGeometryProcessorTextureSupport()) { + caps.dynamicStateArrayGeometryProcessorTextureSupport() && + thisView.swizzle() == thatView.swizzle() && + thisView.origin() == thatView.origin()) { return CombineResult::kMayChain; } return CombineResult::kCannotCombine; @@ -824,7 +841,7 @@ class TextureOp final : public GrMeshDrawOp { // Concatenate quad lists together fQuads.concat(that->fQuads); - fProxyCountPairs[0].fQuadCnt += that->fQuads.count(); + fViewCountPairs[0].fQuadCnt += that->fQuads.count(); fTotNumQuads += that->fQuads.count(); return CombineResult::kMerged; @@ -849,9 +866,9 @@ class TextureOp final : public GrMeshDrawOp { unsigned fProxyCnt : 32 - 8; // This field must go last. When allocating this op, we will allocate extra space to hold - // additional ProxyCountPairs immediately after the op's allocation so we can treat this + // additional ViewCountPairs immediately after the op's allocation so we can treat this // as an fProxyCnt-length array. - ProxyCountPair fProxyCountPairs[1]; + ViewCountPair fViewCountPairs[1]; static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type does not fit in 2 bits"); @@ -863,7 +880,7 @@ class TextureOp final : public GrMeshDrawOp { namespace GrTextureOp { std::unique_ptr Make(GrRecordingContext* context, - sk_sp proxy, + GrSurfaceProxyView proxyView, GrColorType srcColorType, sk_sp textureXform, GrSamplerState::Filter filter, @@ -875,6 +892,7 @@ std::unique_ptr Make(GrRecordingContext* context, const GrQuad& deviceQuad, const GrQuad& localQuad, const SkRect* domain) { + GrTextureProxy* proxy = proxyView.asTextureProxy(); // Apply optimizations that are valid whether or not using GrTextureOp or GrFillRectOp if (domain && domain->contains(proxy->backingStoreBoundsRect())) { // No need for a shader-based domain if hardware clamping achieves the same effect @@ -886,8 +904,8 @@ std::unique_ptr Make(GrRecordingContext* context, } if (blendMode == SkBlendMode::kSrcOver) { - return TextureOp::Make(context, std::move(proxy), std::move(textureXform), filter, color, - saturate, aaType, aaFlags, deviceQuad, localQuad, domain); + return TextureOp::Make(context, std::move(proxyView), std::move(textureXform), filter, + color, saturate, aaType, aaFlags, deviceQuad, localQuad, domain); } else { // Emulate complex blending using GrFillRectOp GrPaint paint; @@ -902,10 +920,10 @@ std::unique_ptr Make(GrRecordingContext* context, SkRect correctedDomain; compute_domain(Domain::kYes, filter, kTopLeft_GrSurfaceOrigin, *domain, 1.f, 1.f, proxy->height(), &correctedDomain); - fp = GrTextureDomainEffect::Make(std::move(proxy), srcColorType, SkMatrix::I(), + fp = GrTextureDomainEffect::Make(sk_ref_sp(proxy), srcColorType, SkMatrix::I(), correctedDomain, GrTextureDomain::kClamp_Mode, filter); } else { - fp = GrSimpleTextureEffect::Make(std::move(proxy), srcColorType, SkMatrix::I(), filter); + fp = GrSimpleTextureEffect::Make(sk_ref_sp(proxy), srcColorType, SkMatrix::I(), filter); } fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform)); paint.addColorFragmentProcessor(std::move(fp)); @@ -984,7 +1002,11 @@ GR_DRAW_OP_TEST_DEFINE(TextureOp) { aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone; bool useDomain = random->nextBool(); auto saturate = random->nextBool() ? GrTextureOp::Saturate::kYes : GrTextureOp::Saturate::kNo; - return GrTextureOp::Make(context, std::move(proxy), GrColorType::kRGBA_8888, + GrSurfaceProxyView proxyView( + std::move(proxy), origin, + context->priv().caps()->getTextureSwizzle(format, GrColorType::kRGBA_8888)); + + return GrTextureOp::Make(context, std::move(proxyView), GrColorType::kRGBA_8888, std::move(texXform), filter, color, saturate, SkBlendMode::kSrcOver, aaType, aaFlags, GrQuad::MakeFromRect(rect, viewMatrix), GrQuad(srcRect), useDomain ? &srcRect : nullptr); diff --git a/src/gpu/ops/GrTextureOp.h b/src/gpu/ops/GrTextureOp.h index da7a6b4eb1911..a4eb15b5965b5 100644 --- a/src/gpu/ops/GrTextureOp.h +++ b/src/gpu/ops/GrTextureOp.h @@ -40,7 +40,7 @@ enum class Saturate : bool { kNo = false, kYes = true }; * src over, this will return a GrFillRectOp with a paint that samples the proxy. */ std::unique_ptr Make(GrRecordingContext*, - sk_sp, + GrSurfaceProxyView, GrColorType srcColorType, sk_sp, GrSamplerState::Filter,