Extract a GrAtlasInstancedHelper subclass

This helper will allow other GPs that use instancing to also clip
against an atlas.

Bug: chromium:928984
Change-Id: I5a3bb221220bace46c6c9d799c2db68e2a2c67b7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/425979
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Chris Dalton 2021-07-08 15:38:51 -06:00 committed by Skia Commit-Bot
parent bdc412f149
commit b1fd64e82e
6 changed files with 245 additions and 105 deletions

View File

@ -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",

View File

@ -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<GrGeometryProcessor::Attribute>* 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());
}

View File

@ -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<GrGeometryProcessor::Attribute>* 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<GrSurfaceProxy> fAtlasProxy;
const GrSwizzle fAtlasSwizzle;
const ShaderFlags fShaderFlags;
};
GR_MAKE_BITFIELD_CLASS_OPS(GrAtlasInstancedHelper::ShaderFlags);
#endif

View File

@ -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<kMaxInstanceAttribs, GrGeometryProcessor::Attribute> fAttribs;
class Impl;
};
@ -72,13 +70,6 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
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<DrawAtlasPathShader>().fAtlasDimensions;
pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height());
auto* atlasHelper = geomProc.cast<DrawAtlasPathShader>().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<GrDrawAtlasPathOp>();
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<GrPipeline>(initArgs, std::move(fProcessors),
std::move(appliedClip));
GrSwizzle swizzle = caps.getReadSwizzle(fAtlasProxy->backendFormat(), GrColorType::kAlpha_8);
auto shader = arena->make<DrawAtlasPathShader>(fAtlasProxy.get(), swizzle, fIsInverseFill,
fUsesLocalCoords, *caps.shaderCaps());
auto shader = arena->make<DrawAtlasPathShader>(fUsesLocalCoords, &fAtlasHelper,
*caps.shaderCaps());
fProgram = arena->make<GrProgramInfo>(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);
}

View File

@ -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<GrTextureProxy> 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<Instance>(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<float, 6> fLocalToDeviceIfUsingLocalCoords;
SkPMColor4f fColor;
SkIPoint16 fLocationInAtlas;
SkIRect fPathDevIBounds;
bool fTransposedInAtlas;
GrAtlasInstancedHelper::Instance fAtlasInstance;
Instance* fNext = nullptr;
};
Instance* fHeadInstance;
Instance** fTailInstance;
const sk_sp<GrTextureProxy> fAtlasProxy;
const bool fIsInverseFill;
GrAtlasInstancedHelper fAtlasHelper;
const bool fEnableHWAA;
bool fUsesLocalCoords = false;

View File

@ -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<GrDrawAtlasPathOp>(
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;