diff --git a/gn/gpu.gni b/gn/gpu.gni index 433e59aded..bdd94d8252 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -375,6 +375,8 @@ skia_gpu_sources = [ "$_src/gpu/gradients/GrGradientShader.h", # tessellate + "$_src/gpu/tessellate/GrAtlasInstancedHelper.cpp", + "$_src/gpu/tessellate/GrAtlasInstancedHelper.h", "$_src/gpu/tessellate/GrAtlasRenderTask.cpp", "$_src/gpu/tessellate/GrAtlasRenderTask.h", "$_src/gpu/tessellate/GrCullTest.h", diff --git a/src/gpu/tessellate/GrAtlasInstancedHelper.cpp b/src/gpu/tessellate/GrAtlasInstancedHelper.cpp new file mode 100644 index 0000000000..19a7638445 --- /dev/null +++ b/src/gpu/tessellate/GrAtlasInstancedHelper.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2020 Google LLC. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "src/gpu/tessellate/GrAtlasInstancedHelper.h" + +#include "src/gpu/GrVertexWriter.h" +#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" +#include "src/gpu/glsl/GrGLSLVarying.h" +#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" + +void GrAtlasInstancedHelper::appendInstanceAttribs( + SkTArray* instanceAttribs) const { + instanceAttribs->emplace_back("locations", kFloat4_GrVertexAttribType, kFloat4_GrSLType); + if (fShaderFlags & ShaderFlags::kCheckBounds) { + instanceAttribs->emplace_back("sizeInAtlas", kFloat2_GrVertexAttribType, kFloat2_GrSLType); + } +} + +void GrAtlasInstancedHelper::writeInstanceData(GrVertexWriter* instanceWriter, + const Instance* i) const { + SkASSERT(i->fLocationInAtlas.x() >= 0); + SkASSERT(i->fLocationInAtlas.y() >= 0); + instanceWriter->write( + // A negative x coordinate in the atlas indicates that the path is transposed. + // Also add 1 since we can't negate zero. + (float)(i->fTransposedInAtlas ? -i->fLocationInAtlas.x() - 1 + : i->fLocationInAtlas.x() + 1), + (float)i->fLocationInAtlas.y(), + (float)i->fPathDevIBounds.left(), + (float)i->fPathDevIBounds.top(), + GrVertexWriter::If(fShaderFlags & ShaderFlags::kCheckBounds, + SkSize::Make(i->fPathDevIBounds.size()))); +} + +void GrAtlasInstancedHelper::injectShaderCode( + const GrGLSLGeometryProcessor::EmitArgs& args, const GrShaderVar& devCoord, + GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const { + GrGLSLVarying atlasCoord(kFloat2_GrSLType); + args.fVaryingHandler->addVarying("atlasCoord", &atlasCoord); + + const char* atlasAdjustName; + *atlasAdjustUniformHandle = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjustName); + + args.fVertBuilder->codeAppendf(R"( + // A negative x coordinate in the atlas indicates that the path is transposed. + // We also added 1 since we can't negate zero. + float2 atlasTopLeft = float2(abs(locations.x) - 1, locations.y); + float2 devTopLeft = locations.zw; + bool transposed = locations.x < 0; + float2 atlasCoord = %s - devTopLeft; + if (transposed) { + atlasCoord = atlasCoord.yx; + } + atlasCoord += atlasTopLeft; + %s = atlasCoord * %s;)", devCoord.c_str(), atlasCoord.vsOut(), atlasAdjustName); + + if (fShaderFlags & ShaderFlags::kCheckBounds) { + GrGLSLVarying atlasBounds(kFloat4_GrSLType); + args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds, + GrGLSLVaryingHandler::Interpolation::kCanBeFlat); + args.fVertBuilder->codeAppendf(R"( + float4 atlasBounds = atlasTopLeft.xyxy + (transposed ? sizeInAtlas.00yx + : sizeInAtlas.00xy); + %s = atlasBounds * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjustName); + + args.fFragBuilder->codeAppendf(R"( + half atlasCoverage = 0; + float2 atlasCoord = %s; + float4 atlasBounds = %s; + if (all(greaterThan(atlasCoord, atlasBounds.xy)) && + all(lessThan(atlasCoord, atlasBounds.zw))) { + atlasCoverage = )", atlasCoord.fsIn(), atlasBounds.fsIn()); + args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlasCoord"); + args.fFragBuilder->codeAppendf(R"(.a; + })"); + } else { + args.fFragBuilder->codeAppendf("half atlasCoverage = "); + args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn()); + args.fFragBuilder->codeAppendf(".a;"); + } + + if (fShaderFlags & ShaderFlags::kInvertCoverage) { + args.fFragBuilder->codeAppendf("%s *= (1 - atlasCoverage);", args.fOutputCoverage); + } else { + args.fFragBuilder->codeAppendf("%s *= atlasCoverage;", args.fOutputCoverage); + } +} + +void GrAtlasInstancedHelper::setUniformData( + const GrGLSLProgramDataManager& pdman, + const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const { + SkASSERT(fAtlasProxy->isInstantiated()); + SkISize dimensions = fAtlasProxy->backingStoreDimensions(); + pdman.set2f(atlasAdjustUniformHandle, 1.f / dimensions.width(), 1.f / dimensions.height()); +} diff --git a/src/gpu/tessellate/GrAtlasInstancedHelper.h b/src/gpu/tessellate/GrAtlasInstancedHelper.h new file mode 100644 index 0000000000..28a7921ea8 --- /dev/null +++ b/src/gpu/tessellate/GrAtlasInstancedHelper.h @@ -0,0 +1,100 @@ +/* + * Copyright 2021 Google LLC. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGrAtlasInstancedHelper_DEFINED +#define GrGrAtlasInstancedHelper_DEFINED + +#include "src/core/SkIPoint16.h" +#include "src/gpu/GrGeometryProcessor.h" +#include "src/gpu/GrSurfaceProxyView.h" +#include "src/gpu/glsl/GrGLSLGeometryProcessor.h" +#include "src/gpu/glsl/GrGLSLUniformHandler.h" + +struct GrVertexWriter; + +// This class encapsulates all the necessary steps for an instanced GrGeometryProcessor to clip +// against a path mask from an atlas. +class GrAtlasInstancedHelper { +public: + enum class ShaderFlags { + kNone = 0, + kInvertCoverage = 1 << 0, + kCheckBounds = 1 << 1 + }; + + GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(ShaderFlags); + + constexpr static int kNumShaderFlags = 2; + + GrAtlasInstancedHelper(GrSurfaceProxyView atlasView, ShaderFlags shaderFlags) + : fAtlasProxy(atlasView.detachProxy()) + , fAtlasSwizzle(atlasView.swizzle()) + , fShaderFlags(shaderFlags) { + // Bottom left origin is not supported. + SkASSERT(atlasView.origin() == kTopLeft_GrSurfaceOrigin); + } + + GrSurfaceProxy* proxy() const { return fAtlasProxy.get(); } + const GrSwizzle& atlasSwizzle() const { return fAtlasSwizzle; } + + // Returns whether the two helpers can be batched together in a single draw. + bool isCompatible(const GrAtlasInstancedHelper& helper) { + // TODO: We may want to consider two helpers compatible if they only differ in the + // kCheckBounds flag -- we can always promote one to checking its bounds. + SkASSERT(fAtlasProxy != helper.fAtlasProxy || fAtlasSwizzle == helper.fAtlasSwizzle); + return fAtlasProxy == helper.fAtlasProxy && fShaderFlags == helper.fShaderFlags; + } + + // Adds bits to the shader key that uniquely identify this specific helper's shader code. + void getKeyBits(GrProcessorKeyBuilder* b) const { + b->addBits(kNumShaderFlags, (int)fShaderFlags, "atlasFlags"); + } + + // Appends the instanced input attribs to the back of the array that we will need in order to + // locate our path in the atlas. + void appendInstanceAttribs(SkTArray* instanceAttribs) const; + + struct Instance { + Instance(SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds, bool transposedInAtlas) + : fLocationInAtlas(locationInAtlas) + , fPathDevIBounds(pathDevIBounds) + , fTransposedInAtlas(transposedInAtlas) { + SkASSERT(fLocationInAtlas.x() >= 0); + SkASSERT(fLocationInAtlas.y() >= 0); + } + SkIPoint16 fLocationInAtlas; + SkIRect fPathDevIBounds; + bool fTransposedInAtlas; + }; + + // Writes out the given instance data, formatted for the specific attribs that we added during + // appendInstanceAttribs(). + void writeInstanceData(GrVertexWriter* instanceWriter, const Instance*) const; + + // Injects vertex code, fragment code, varyings, and uniforms to ultimately multiply + // "args.fOutputCoverage" in the fragment shader by the atlas coverage. + // + // The caller is responsible to store "atlasAdjustUniformHandle" and pass it to + // setUniformData(). + void injectShaderCode(const GrGLSLGeometryProcessor::EmitArgs&, const GrShaderVar& devCoord, + GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const; + + // The atlas clip requires one uniform value -- "atlasAdjustUniform". The caller should have + // stored this handle after its call to injectShaderCode(). This method sets its value prior to + // drawing. + void setUniformData(const GrGLSLProgramDataManager&, + const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const; + +private: + const sk_sp fAtlasProxy; + const GrSwizzle fAtlasSwizzle; + const ShaderFlags fShaderFlags; +}; + +GR_MAKE_BITFIELD_CLASS_OPS(GrAtlasInstancedHelper::ShaderFlags); + +#endif diff --git a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp index 5089b21d01..f240ae433c 100644 --- a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp +++ b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp @@ -12,7 +12,6 @@ #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrResourceProvider.h" #include "src/gpu/GrVertexWriter.h" -#include "src/gpu/GrVx.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" #include "src/gpu/glsl/GrGLSLGeometryProcessor.h" #include "src/gpu/glsl/GrGLSLVarying.h" @@ -22,13 +21,13 @@ namespace { class DrawAtlasPathShader : public GrGeometryProcessor { public: - DrawAtlasPathShader(const GrTextureProxy* atlasProxy, GrSwizzle swizzle, bool isInverseFill, - bool usesLocalCoords, const GrShaderCaps& shaderCaps) + DrawAtlasPathShader(bool usesLocalCoords, const GrAtlasInstancedHelper* atlasHelper, + const GrShaderCaps& shaderCaps) : GrGeometryProcessor(kDrawAtlasPathShader_ClassID) - , fAtlasAccess(GrSamplerState::Filter::kNearest, atlasProxy->backendFormat(), swizzle) - , fAtlasDimensions(atlasProxy->backingStoreDimensions()) - , fIsInverseFill(isInverseFill) - , fUsesLocalCoords(usesLocalCoords) { + , fUsesLocalCoords(usesLocalCoords) + , fAtlasHelper(atlasHelper) + , fAtlasAccess(GrSamplerState::Filter::kNearest, fAtlasHelper->proxy()->backendFormat(), + fAtlasHelper->atlasSwizzle()) { if (!shaderCaps.vertexIDSupport()) { constexpr static Attribute kUnitCoordAttrib("unitCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType); @@ -41,10 +40,8 @@ public: } SkASSERT(fAttribs.count() == this->colorAttribIdx()); fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType); - fAttribs.emplace_back("locations", kFloat4_GrVertexAttribType, kFloat4_GrSLType); - if (fIsInverseFill) { - fAttribs.emplace_back("sizeInAtlas", kFloat2_GrVertexAttribType, kFloat2_GrSLType); - } + fAtlasHelper->appendInstanceAttribs(&fAttribs); + SkASSERT(fAttribs.count() <= kMaxInstanceAttribs); this->setInstanceAttributes(fAttribs.data(), fAttribs.count()); this->setTextureSamplerCnt(1); } @@ -53,16 +50,17 @@ private: int colorAttribIdx() const { return fUsesLocalCoords ? 3 : 1; } const char* name() const override { return "DrawAtlasPathShader"; } void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { - b->add32((fUsesLocalCoords << 1) | (int)fIsInverseFill); + b->addBits(1, fUsesLocalCoords, "localCoords"); + fAtlasHelper->getKeyBits(b); } const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; } GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override; - const TextureSampler fAtlasAccess; - const SkISize fAtlasDimensions; - const bool fIsInverseFill; const bool fUsesLocalCoords; - SkSTArray<6, GrGeometryProcessor::Attribute> fAttribs; + const GrAtlasInstancedHelper* const fAtlasHelper; + TextureSampler fAtlasAccess; + constexpr static int kMaxInstanceAttribs = 6; + SkSTArray fAttribs; class Impl; }; @@ -72,13 +70,6 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor { const auto& shader = args.fGeomProc.cast(); args.fVaryingHandler->emitAttributes(shader); - GrGLSLVarying atlasCoord(kFloat2_GrSLType); - args.fVaryingHandler->addVarying("atlasCoord", &atlasCoord); - - const char* atlasAdjust; - fAtlasAdjustUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "atlas_adjust", &atlasAdjust); - if (args.fShaderCaps->vertexIDSupport()) { // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex // attrib. @@ -97,44 +88,8 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor { gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localCoord"); } - args.fVertBuilder->codeAppendf(R"( - // A negative x coordinate in the atlas indicates that the path is transposed. - // We also added 1 since we can't negate zero. - float2 atlasTopLeft = float2(abs(locations.x) - 1, locations.y); - float2 devTopLeft = locations.zw; - bool transposed = locations.x < 0; - float2 atlasCoord = devCoord - devTopLeft; - if (transposed) { - atlasCoord = atlasCoord.yx; - } - atlasCoord += atlasTopLeft; - %s = atlasCoord * %s;)", atlasCoord.vsOut(), atlasAdjust); - - if (shader.fIsInverseFill) { - GrGLSLVarying atlasBounds(kFloat4_GrSLType); - args.fVaryingHandler->addVarying("atlasbounds", &atlasBounds, - GrGLSLVaryingHandler::Interpolation::kCanBeFlat); - args.fVertBuilder->codeAppendf(R"( - float4 atlasBounds = atlasTopLeft.xyxy + (transposed ? sizeInAtlas.00yx - : sizeInAtlas.00xy); - %s = atlasBounds * %s.xyxy;)", atlasBounds.vsOut(), atlasAdjust); - - args.fFragBuilder->codeAppendf(R"( - half coverage = 0; - float2 atlasCoord = %s; - float4 atlasBounds = %s; - if (all(greaterThan(atlasCoord, atlasBounds.xy)) && - all(lessThan(atlasCoord, atlasBounds.zw))) { - coverage = )", atlasCoord.fsIn(), atlasBounds.fsIn()); - args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], "atlasCoord"); - args.fFragBuilder->codeAppendf(R"(.a; - } - half4 %s = half4(1 - coverage);)", args.fOutputCoverage); - } else { - args.fFragBuilder->codeAppendf("half4 %s = ", args.fOutputCoverage); - args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn()); - args.fFragBuilder->codeAppendf(".aaaa;"); - } + args.fFragBuilder->codeAppendf("half4 %s = half4(1);", args.fOutputCoverage); + shader.fAtlasHelper->injectShaderCode(args, gpArgs->fPositionVar, &fAtlasAdjustUniform); args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor); args.fVaryingHandler->addPassThroughAttribute( @@ -145,8 +100,8 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor { void setData(const GrGLSLProgramDataManager& pdman, const GrShaderCaps&, const GrGeometryProcessor& geomProc) override { - const SkISize& dimensions = geomProc.cast().fAtlasDimensions; - pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height()); + auto* atlasHelper = geomProc.cast().fAtlasHelper; + atlasHelper->setUniformData(pdman, fAtlasAdjustUniform); } GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform; @@ -167,13 +122,12 @@ GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const G return analysis; } -GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible( - GrOp* op, SkArenaAlloc* alloc, const GrCaps&) { +GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible(GrOp* op, SkArenaAlloc*, const GrCaps&) { auto* that = op->cast(); - SkASSERT(fAtlasProxy == that->fAtlasProxy); SkASSERT(fEnableHWAA == that->fEnableHWAA); - if (fIsInverseFill != that->fIsInverseFill || fProcessors != that->fProcessors) { + if (!fAtlasHelper.isCompatible(that->fAtlasHelper) || + fProcessors != that->fProcessors) { return CombineResult::kCannotCombine; } @@ -200,9 +154,8 @@ void GrDrawAtlasPathOp::prepareProgram(const GrCaps& caps, SkArenaAlloc* arena, initArgs.fWriteSwizzle = writeView.swizzle(); auto pipeline = arena->make(initArgs, std::move(fProcessors), std::move(appliedClip)); - GrSwizzle swizzle = caps.getReadSwizzle(fAtlasProxy->backendFormat(), GrColorType::kAlpha_8); - auto shader = arena->make(fAtlasProxy.get(), swizzle, fIsInverseFill, - fUsesLocalCoords, *caps.shaderCaps()); + auto shader = arena->make(fUsesLocalCoords, &fAtlasHelper, + *caps.shaderCaps()); fProgram = arena->make(writeView, pipeline, &GrUserStencilSettings::kUnused, shader, GrPrimitiveType::kTriangleStrip, 0, renderPassXferBarriers, colorLoadOp); @@ -233,23 +186,13 @@ void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* flushState) { if (GrVertexWriter instanceWriter = flushState->makeVertexSpace( fProgram->geomProc().instanceStride(), fInstanceCount, &fInstanceBuffer, &fBaseInstance)) { - for (const Instance* instance = fHeadInstance; instance; instance = instance->fNext) { - SkASSERT(instance->fLocationInAtlas.x() >= 0); - SkASSERT(instance->fLocationInAtlas.y() >= 0); + for (const Instance* i = fHeadInstance; i; i = i->fNext) { instanceWriter.write( - SkRect::Make(instance->fFillBounds), + SkRect::Make(i->fFillBounds), GrVertexWriter::If(fUsesLocalCoords, - instance->fLocalToDeviceIfUsingLocalCoords), - instance->fColor, - // A negative x coordinate in the atlas indicates that the path is transposed. - // Also add 1 since we can't negate zero. - (float)(instance->fTransposedInAtlas ? -instance->fLocationInAtlas.x() - 1 - : instance->fLocationInAtlas.x() + 1), - (float)instance->fLocationInAtlas.y(), - (float)instance->fPathDevIBounds.left(), - (float)instance->fPathDevIBounds.top(), - GrVertexWriter::If(fIsInverseFill, - SkSize::Make(instance->fPathDevIBounds.size()))); + i->fLocalToDeviceIfUsingLocalCoords), + i->fColor); + fAtlasHelper.writeInstanceData(&instanceWriter, &i->fAtlasInstance); } } @@ -264,9 +207,8 @@ void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* flushState) { } void GrDrawAtlasPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) { - SkASSERT(fAtlasProxy->isInstantiated()); flushState->bindPipelineAndScissorClip(*fProgram, this->bounds()); - flushState->bindTextures(fProgram->geomProc(), *fAtlasProxy, fProgram->pipeline()); + flushState->bindTextures(fProgram->geomProc(), *fAtlasHelper.proxy(), fProgram->pipeline()); flushState->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport); flushState->drawInstanced(fInstanceCount, fBaseInstance, 4, 0); } diff --git a/src/gpu/tessellate/GrDrawAtlasPathOp.h b/src/gpu/tessellate/GrDrawAtlasPathOp.h index 827ff0275b..c900dfdabd 100644 --- a/src/gpu/tessellate/GrDrawAtlasPathOp.h +++ b/src/gpu/tessellate/GrDrawAtlasPathOp.h @@ -10,24 +10,26 @@ #include "src/core/SkIPoint16.h" #include "src/gpu/ops/GrDrawOp.h" +#include "src/gpu/tessellate/GrAtlasInstancedHelper.h" // Fills a rectangle of pixels with a clip against coverage values from an atlas. class GrDrawAtlasPathOp : public GrDrawOp { public: DEFINE_OP_CLASS_ID - GrDrawAtlasPathOp(SkArenaAlloc* arena, const SkIRect& fillBounds, - const SkMatrix& localToDevice, GrPaint&& paint, - SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds, - bool transposedInAtlas, sk_sp atlasProxy, bool isInverseFill, + GrDrawAtlasPathOp(SkArenaAlloc* arena, const SkIRect& fillBounds, const SkMatrix& localToDevice, + GrPaint&& paint, SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds, + bool transposedInAtlas, GrSurfaceProxyView atlasView, bool isInverseFill, int numRenderTargetSamples) : GrDrawOp(ClassID()) , fHeadInstance(arena->make(fillBounds, localToDevice, paint.getColor4f(), locationInAtlas, pathDevIBounds, transposedInAtlas)) , fTailInstance(&fHeadInstance->fNext) - , fAtlasProxy(std::move(atlasProxy)) - , fIsInverseFill(isInverseFill) + , fAtlasHelper(std::move(atlasView), + isInverseFill ? GrAtlasInstancedHelper::ShaderFlags::kCheckBounds | + GrAtlasInstancedHelper::ShaderFlags::kInvertCoverage + : GrAtlasInstancedHelper::ShaderFlags::kNone) , fEnableHWAA(numRenderTargetSamples > 1) , fProcessors(std::move(paint)) { this->setBounds(SkRect::Make(fillBounds), HasAABloat::kYes, IsHairline::kNo); @@ -38,7 +40,7 @@ public: return fEnableHWAA ? FixedFunctionFlags::kUsesHWAA : FixedFunctionFlags::kNone; } void visitProxies(const GrVisitProxyFunc& func) const override { - func(fAtlasProxy.get(), GrMipmapped::kNo); + func(fAtlasHelper.proxy(), GrMipmapped::kNo); fProcessors.visitProxies(func); } GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override; @@ -63,26 +65,19 @@ private: m.getSkewX(), m.getScaleY(), m.getTranslateX(), m.getTranslateY()} , fColor(color) - , fLocationInAtlas(locationInAtlas) - , fPathDevIBounds(pathDevIBounds) - , fTransposedInAtlas(transposedInAtlas) { - SkASSERT(fLocationInAtlas.x() >= 0); - SkASSERT(fLocationInAtlas.y() >= 0); + , fAtlasInstance(locationInAtlas, pathDevIBounds, transposedInAtlas) { } SkIRect fFillBounds; std::array fLocalToDeviceIfUsingLocalCoords; SkPMColor4f fColor; - SkIPoint16 fLocationInAtlas; - SkIRect fPathDevIBounds; - bool fTransposedInAtlas; + GrAtlasInstancedHelper::Instance fAtlasInstance; Instance* fNext = nullptr; }; Instance* fHeadInstance; Instance** fTailInstance; - const sk_sp fAtlasProxy; - const bool fIsInverseFill; + GrAtlasInstancedHelper fAtlasHelper; const bool fEnableHWAA; bool fUsesLocalCoords = false; diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/src/gpu/tessellate/GrTessellationPathRenderer.cpp index c4d8338114..bef36ed329 100644 --- a/src/gpu/tessellate/GrTessellationPathRenderer.cpp +++ b/src/gpu/tessellate/GrTessellationPathRenderer.cpp @@ -170,6 +170,7 @@ bool GrTessellationPathRenderer::onDrawPath(const DrawPathArgs& args) { if (this->tryAddPathToAtlas(args.fContext, *args.fViewMatrix, path, pathDevBounds, args.fAAType != GrAAType::kNone, &devIBounds, &locationInAtlas, &transposedInAtlas, visitProxiesUsedByDraw)) { + const GrCaps& caps = *args.fSurfaceDrawContext->caps(); const SkIRect& fillBounds = path.isInverseFillType() ? (args.fClip ? args.fClip->getConservativeBounds() @@ -178,7 +179,7 @@ bool GrTessellationPathRenderer::onDrawPath(const DrawPathArgs& args) { auto op = GrOp::Make( args.fContext, args.fSurfaceDrawContext->arenaAlloc(), fillBounds, *args.fViewMatrix, std::move(args.fPaint), locationInAtlas, devIBounds, - transposedInAtlas, sk_ref_sp(fAtlasRenderTasks.back()->atlasProxy()), + transposedInAtlas, fAtlasRenderTasks.back()->readView(caps), path.isInverseFillType(), surfaceDrawContext->numSamples()); surfaceDrawContext->addDrawOp(args.fClip, std::move(op)); return true;