43 const float coverage[4],
47 static constexpr auto If = VertexWriter::If<float>;
52 for (
int i = 0; i < 4; ++i) {
55 *vb << deviceQuad->
x(i)
62 bool wide = spec.
colorType() == ColorType::kFloat;
68 *vb << localQuad->
x(i)
94 const float coverage[4],
110 bool wide = spec.
colorType() == ColorType::kFloat;
111 for (
int i = 0; i < 4; ++i) {
114 *vb << deviceQuad->
x(i)
126 const float coverage[4],
129 const SkRect& texSubset) {
139 for (
int i = 0; i < 4; ++i) {
140 *vb << deviceQuad->
x(i)
153 const float coverage[4],
156 const SkRect& texSubset) {
167 bool wide = spec.
colorType() == ColorType::kFloat;
168 for (
int i = 0; i < 4; ++i) {
171 *vb << deviceQuad->
x(i)
185 const float coverage[4],
188 const SkRect& texSubset) {
198 for (
int i = 0; i < 4; ++i) {
199 *vb << deviceQuad->
x(i)
219 const float coverage[4],
222 const SkRect& texSubset) {
232 for (
int i = 0; i < 4; ++i) {
233 *vb << deviceQuad->
x(i)
247 const float coverage[4],
250 const SkRect& texSubset) {
261 bool wide = spec.
colorType() == ColorType::kFloat;
262 for (
int i = 0; i < 4; ++i) {
265 *vb << deviceQuad->
x(i)
280 const float coverage[4],
283 const SkRect& texSubset) {
293 for (
int i = 0; i < 4; ++i) {
294 *vb << deviceQuad->
x(i)
307 return IndexBufferOption::kPictureFramed;
308 }
else if (numQuads > 1) {
309 return IndexBufferOption::kIndexedRects;
311 return IndexBufferOption::kTriStrips;
318 return ColorType::kNone;
320 return color.fitsInBytes() ? ColorType::kByte : ColorType::kFloat;
337 return write_2d_color;
340 return spec.
hasSubset() ? write_2d_color_uv_strict : write_2d_color_uv;
349 return spec.
hasSubset() ? write_2d_cov_uv_strict : write_2d_cov_uv;
352 return spec.
hasSubset() ? write_2d_uv_strict : write_2d_uv;
360 return write_quad_generic;
365 , fVertexWriter{vertices}
366 , fWriteProc(
Tessellator::GetWriteQuadProc(spec)) {}
377 static const float kFullCoverage[4] = {1.f, 1.f, 1.f, 1.f};
378 static const float kZeroCoverage[4] = {0.f, 0.f, 0.f, 0.f};
401 geomSubset, uvSubset);
405 geomSubset, uvSubset);
414 edgeDistances = 0.5f;
426 geomSubset, uvSubset);
442 skvx::shuffle<2, 3, 0, 1>(len));
445 edgeDistances *=
max(1.f, 2.f - maxWH);
449 geomSubset, uvSubset);
456 kIgnoredSubset, uvSubset);
462 auto resourceProvider =
target->resourceProvider();
464 switch (indexBufferOption) {
465 case IndexBufferOption::kPictureFramed:
return resourceProvider->refAAQuadIndexBuffer();
466 case IndexBufferOption::kIndexedRects:
return resourceProvider->refNonAAQuadIndexBuffer();
467 case IndexBufferOption::kTriStrips:
468 default:
return nullptr;
476 case IndexBufferOption::kTriStrips:
return SK_MaxS32;
483 int runningQuadCount,
int quadsInDraw,
int maxVerts,
int absVertBufferOffset) {
485 int offset = absVertBufferOffset +
494 int maxNumQuads, numIndicesPerQuad, numVertsPerQuad;
508 SkASSERT(runningQuadCount + quadsInDraw <= maxNumQuads);
514 int offset = absVertBufferOffset + runningQuadCount * numVertsPerQuad;
516 renderPass->
drawIndexPattern(numIndicesPerQuad, quadsInDraw, maxNumQuads, numVertsPerQuad,
519 int baseIndex = runningQuadCount * numIndicesPerQuad;
520 int numIndicesToDraw = quadsInDraw * numIndicesPerQuad;
522 int minVertex = runningQuadCount * numVertsPerQuad;
523 int maxVertex = (runningQuadCount + quadsInDraw) * numVertsPerQuad - 1;
525 renderPass->
drawIndexed(numIndicesToDraw, baseIndex, minVertex, maxVertex,
526 absVertBufferOffset);
564 if (needsPerspective) {
571 if (needsPerspective) {
584 if (ColorType::kByte == this->
colorType()) {
586 }
else if (ColorType::kFloat == this->
colorType()) {
602 return arena->
make([&](
void* ptr) {
615 return arena->
make([&](
void* ptr) {
617 vertexSpec, caps, backendFormat, samplerState, swizzle,
618 std::move(textureColorSpaceXform), saturate);
622 const char*
name()
const override {
return "QuadPerEdgeAAGeometryProcessor"; }
628 b->addBool(fNeedsPerspective,
"perspective");
629 b->addBool((fSaturate == Saturate::kYes),
"saturate");
643 uint32_t coverageKey = 0;
650 b->addBits(2, coverageKey,
"coverageMode");
662 fTextureColorSpaceXformHelper.setData(pdman, gp.fTextureColorSpaceXform.get());
666 void onEmitCode(EmitArgs&
args, GrGPArgs* gpArgs)
override {
670 fTextureColorSpaceXformHelper.emitCode(
args.fUniformHandler,
671 gp.fTextureColorSpaceXform.get());
673 args.fVaryingHandler->emitAttributes(gp);
675 if (gp.fCoverageMode == CoverageMode::kWithPosition) {
678 if (gp.fNeedsPerspective) {
679 args.fVertBuilder->codeAppendf(
"float3 position = %s.xyz;",
680 gp.fPosition.name());
682 args.fVertBuilder->codeAppendf(
"float2 position = %s.xy;",
683 gp.fPosition.name());
685 gpArgs->fPositionVar = {
"position",
691 gpArgs->fPositionVar = gp.fPosition.asShaderVar();
697 gpArgs->fLocalCoordVar = gp.fLocalCoord.asShaderVar();
700 const char* blendDst;
701 if (gp.fColor.isInitialized()) {
702 SkASSERT(gp.fCoverageMode != CoverageMode::kWithColor || !gp.fNeedsPerspective);
704 args.fFragBuilder->codeAppendf(
"half4 %s;",
args.fOutputColor);
705 args.fVaryingHandler->addPassThroughAttribute(
706 gp.fColor.asShaderVar(),
708 gp.fCoverageMode == CoverageMode::kWithColor
709 ? Interpolation::kInterpolated
710 : Interpolation::kCanBeFlat);
711 blendDst =
args.fOutputColor;
714 args.fFragBuilder->codeAppendf(
"half4 %s = half4(1);",
args.fOutputColor);
720 if (gp.fSampler.isInitialized()) {
723 args.fFragBuilder->codeAppend(
"float2 texCoord;");
727 args.fVaryingHandler->addVarying(gp.fLocalCoord.name(), &v);
728 args.fVertBuilder->codeAppendf(
"%s = %s;",
729 v.
vsOut(), gp.fLocalCoord.name());
730 args.fFragBuilder->codeAppendf(
"texCoord = %s.xy / %s.z;",
733 args.fVaryingHandler->addPassThroughAttribute(gp.fLocalCoord.asShaderVar(),
738 if (gp.fTexSubset.isInitialized()) {
739 args.fFragBuilder->codeAppend(
"float4 subset;");
740 args.fVaryingHandler->addPassThroughAttribute(gp.fTexSubset.asShaderVar(),
742 Interpolation::kCanBeFlat);
743 args.fFragBuilder->codeAppend(
744 "texCoord = clamp(texCoord, subset.LT, subset.RB);");
748 args.fFragBuilder->codeAppendf(
751 (gp.fSaturate == Saturate::kYes) ?
"saturate" :
"");
752 args.fFragBuilder->appendTextureLookupAndBlend(
754 "texCoord", &fTextureColorSpaceXformHelper);
755 args.fFragBuilder->codeAppend(
");");
759 SkASSERT(gp.fSaturate == Saturate::kNo);
763 if (gp.fCoverageMode == CoverageMode::kWithPosition) {
765 args.fVaryingHandler->addVarying(
"coverage", &coverage);
766 if (gp.fNeedsPerspective) {
769 args.fVertBuilder->codeAppendf(
"%s = %s.w * %s.z;",
770 coverage.vsOut(), gp.fPosition.name(),
771 gp.fPosition.name());
772 args.fFragBuilder->codeAppendf(
"float coverage = %s * sk_FragCoord.w;",
775 args.fVertBuilder->codeAppendf(
"%s = %s;",
776 coverage.vsOut(), gp.fCoverage.name());
777 args.fFragBuilder->codeAppendf(
"float coverage = %s;", coverage.fsIn());
780 if (gp.fGeomSubset.isInitialized()) {
785 args.fFragBuilder->codeAppend(
"float4 geoSubset;");
786 args.fVaryingHandler->addPassThroughAttribute(gp.fGeomSubset.asShaderVar(),
788 Interpolation::kCanBeFlat);
789 args.fFragBuilder->codeAppend(
791 "float4 dists4 = saturate(float4(1, 1, -1, -1) * "
792 "(sk_FragCoord.xyxy - geoSubset));"
793 "float2 dists2 = dists4.xy + dists4.zw - 1;"
794 "coverage = min(coverage, dists2.x * dists2.y);");
797 args.fFragBuilder->codeAppendf(
"half4 %s = half4(coverage);",
798 args.fOutputCoverage);
802 SkASSERT(!gp.fGeomSubset.isInitialized());
803 args.fFragBuilder->codeAppendf(
"const half4 %s = half4(1);",
804 args.fOutputCoverage);
811 return std::make_unique<Impl>();
819 , fTextureColorSpaceXform(nullptr) {
821 this->initializeAttrs(spec);
825 QuadPerEdgeAAGeometryProcessor(
const VertexSpec& spec,
833 , fSaturate(saturate)
834 , fTextureColorSpaceXform(
std::move(textureColorSpaceXform))
835 , fSampler(samplerState, backendFormat, swizzle) {
837 this->initializeAttrs(spec);
842 void initializeAttrs(
const VertexSpec& spec) {
847 if (fNeedsPerspective) {
854 if (fNeedsPerspective) {
870 }
else if (localDim == 2) {
896 bool fNeedsPerspective;
904 TextureSampler fSampler;
922 swizzle, std::move(textureColorSpaceXform),
static constexpr size_t GrVertexAttribTypeSize(GrVertexAttribType type)
@ kFloat2_GrVertexAttribType
@ kUByte4_norm_GrVertexAttribType
@ kFloat3_GrVertexAttribType
@ kFloat_GrVertexAttribType
@ kFloat4_GrVertexAttribType
constexpr SkPMColor4f SK_PMColor4fWHITE
static constexpr int32_t SK_MaxS32
Type::kYUV Type::kRGBA() int(0.7 *637)
bool avoidLargeIndexBufferDraws() const
const char * vsOut() const
const char * fsIn() const
constexpr GrVertexAttribType cpuType() const
constexpr bool isInitialized() const
bool isInitialized() const
void setTextureSamplerCnt(int cnt)
static Attribute MakeColorAttribute(const char *name, bool wideColor)
void setVertexAttributesWithImplicitOffsets(const Attribute *attrs, int attrCount)
void draw(int vertexCount, int baseVertex)
void drawIndexPattern(int patternIndexCount, int patternRepeatCount, int maxPatternRepetitionsInIndexBuffer, int patternVertexCount, int baseVertex)
void drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue, int baseVertex)
@ kQuadPerEdgeAAGeometryProcessor_ClassID
void reset(const GrQuad &deviceQuad, const GrQuad *localQuad)
void outset(const skvx::float4 &edgeDistances, GrQuad *deviceOutset, GrQuad *localOutset)
skvx::float4 inset(const skvx::float4 &edgeDistances, GrQuad *deviceInset, GrQuad *localInset)
skvx::float4 getEdgeLengths()
static int NumIndicesPerNonAAQuad()
static int MaxNumNonAAQuads()
static int MaxNumAAQuads()
static int NumIndicesPerAAQuad()
static int NumVertsPerAAQuad()
static int NumVertsPerNonAAQuad()
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const override
static GrGeometryProcessor * Make(SkArenaAlloc *arena, const VertexSpec &spec)
const char * name() const override
static GrGeometryProcessor * Make(SkArenaAlloc *arena, const VertexSpec &vertexSpec, const GrShaderCaps &caps, const GrBackendFormat &backendFormat, GrSamplerState samplerState, const skgpu::Swizzle &swizzle, sk_sp< GrColorSpaceXform > textureColorSpaceXform, Saturate saturate)
const TextureSampler & onTextureSampler(int) const override
void addToKey(const GrShaderCaps &, KeyBuilder *b) const override
GrQuadUtils::TessellationHelper fAAHelper
VertexWriter fVertexWriter
static SkDEBUGCODE(skgpu::BufferWriter::Mark vertexMark() const { return fVertexWriter.mark();}) private WriteQuadProc GetWriteQuadProc(const VertexSpec &spec)
void append(GrQuad *deviceQuad, GrQuad *localQuad, const SkPMColor4f &color, const SkRect &uvSubset, GrQuadAAFlags aaFlags)
Tessellator(const VertexSpec &spec, char *vertices)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float max(float r, float g, float b)
int QuadLimit(IndexBufferOption option)
GrGeometryProcessor * MakeProcessor(SkArenaAlloc *arena, const VertexSpec &spec)
IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads)
GrGeometryProcessor * MakeTexturedProcessor(SkArenaAlloc *arena, const VertexSpec &spec, const GrShaderCaps &caps, const GrBackendFormat &backendFormat, GrSamplerState samplerState, const skgpu::Swizzle &swizzle, sk_sp< GrColorSpaceXform > textureColorSpaceXform, Saturate saturate)
ColorType MinColorType(SkPMColor4f color)
sk_sp< const GrBuffer > GetIndexBuffer(GrMeshDrawTarget *target, IndexBufferOption indexBufferOption)
void IssueDraw(const GrCaps &caps, GrOpsRenderPass *renderPass, const VertexSpec &spec, int runningQuadCount, int quadsInDraw, int maxVerts, int absVertBufferOffset)
static constexpr SkRect MakeEmpty()
SkRect makeOutset(float dx, float dy) const
int deviceDimensionality() const
bool hasVertexColors() const
bool hasLocalCoords() const
IndexBufferOption indexBufferOption() const
int localDimensionality() const
size_t vertexSize() const
bool usesCoverageAA() const
bool requiresGeometrySubset() const
GrQuad::Type deviceQuadType() const
ColorType colorType() const
GrQuad::Type localQuadType() const
bool compatibleWithCoverageAsAlpha() const
CoverageMode coverageMode() const
SKVX_ALWAYS_INLINE void store(void *ptr) const