73 verts[0].
set(rect.fLeft + rad, rect.fTop + rad);
74 verts[1].
set(rect.fLeft - rad, rect.fTop - rad);
75 verts[2].
set(rect.fRight - rad, rect.fTop + rad);
76 verts[3].
set(rect.fRight + rad, rect.fTop - rad);
77 verts[4].
set(rect.fRight - rad, rect.fBottom - rad);
78 verts[5].
set(rect.fRight + rad, rect.fBottom + rad);
79 verts[6].
set(rect.fLeft + rad, rect.fBottom - rad);
80 verts[7].
set(rect.fLeft - rad, rect.fBottom + rad);
86 if (2*rad >= rect.width()) {
87 verts[0].
fX = verts[2].
fX = verts[4].
fX = verts[6].
fX = verts[8].
fX = rect.centerX();
89 if (2*rad >= rect.height()) {
90 verts[0].
fY = verts[2].
fY = verts[4].
fY = verts[6].
fY = verts[8].
fY = rect.centerY();
101 const char*
name()
const override {
return "NonAAStrokeRectOp"; }
128 return Helper::FactoryHelper<NonAAStrokeRectOp>(context, std::move(
paint), inputFlags,
137 , fHelper(processorSet, aaType, inputFlags) {
147 bounds.outset(rad, rad);
160 bounds.offset(0.5f, 0.5f);
161 this->setBounds(bounds, HasAABloat::kNo, IsHairline::kNo);
163 HasAABloat aaBloat = (aaType ==
GrAAType::kNone) ? HasAABloat ::kNo : HasAABloat::kYes;
164 this->setTransformedBounds(bounds,
fViewMatrix, aaBloat,
165 fStrokeWidth ? IsHairline::kNo : IsHairline::kYes);
169 FixedFunctionFlags fixedFunctionFlags()
const override {
return fHelper.
fixedFunctionFlags(); }
179 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
181 void onCreateProgramInfo(
const GrCaps* caps,
184 bool usesMSAASurface,
194 ? LocalCoords::kUsePosition_Type
195 : LocalCoords::kUnused_Type;
203 fProgramInfo = fHelper.
createProgramInfo(caps, arena, writeView, usesMSAASurface,
204 std::move(
clip), dstProxyView, gp, primType,
205 renderPassXferBarriers, colorLoadOp);
210 this->createProgramInfo(
target);
214 int vertexCount = kVertsPerHairlineRect;
215 if (fStrokeWidth > 0) {
216 vertexCount = kVertsPerStrokeRect;
223 target->makeVertexSpace(kVertexStride, vertexCount, &vertexBuffer, &firstVertex);
226 SkDebugf(
"Could not allocate vertices\n");
232 if (fStrokeWidth > 0) {
233 init_nonaa_stroke_rect_strip(vertex,
fRect, fStrokeWidth);
243 fMesh =
target->allocMesh();
244 fMesh->
set(std::move(vertexBuffer), vertexCount, firstVertex);
257#if defined(GR_TEST_UTILS)
258 SkString onDumpInfo()
const override {
259 return SkStringPrintf(
"Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
260 "StrokeWidth: %.2f\n%s",
262 fRect.
fBottom, fStrokeWidth, fHelper.dumpInfo().c_str());
276 const static int kVertsPerHairlineRect = 5;
277 const static int kVertsPerStrokeRect = 10;
289bool stroke_dev_half_size_supported(
SkVector devHalfStrokeSize) {
299 std::min(devHalfStrokeSize.
fX, devHalfStrokeSize.
fY) >= .5f;
302bool compute_aa_rects(
const GrCaps& caps,
316 devStrokeSize.
setAbs(devStrokeSize);
326 devHalfStrokeSize->
fX = rx;
327 devHalfStrokeSize->
fY = ry;
330 viewMatrix.
mapRect(&devRect, rect);
336 if (!devRect.
intersect(visibilityBounds)) {
340 *devOutside = devRect;
341 *devOutsideAssist = devRect;
342 *devInside = devRect;
344 devOutside->
outset(rx, ry);
345 devInside->
inset(rx, ry);
354 spare = std::min(
w,
h);
357 *isDegenerate = spare <= 0;
367 devOutside->
inset(0, ry);
368 devOutsideAssist->
outset(0, ry);
375 bool usesMSAASurface,
376 bool tweakAlphaForCoverage,
378 bool usesLocalCoords,
385 Coverage::Type coverageType = usesMSAASurface ? Coverage::kAttributeUnclamped_Type
386 : (!tweakAlphaForCoverage ? Coverage::kAttribute_Type
387 : Coverage::kSolid_Type);
389 usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type;
391 wideColor ? Color::kPremulWideColorAttribute_Type: Color::kPremulGrColorAttribute_Type;
393 return MakeForDeviceSpace(arena,
colorType, coverageType, localCoordsType, viewMatrix);
418 const SkVector& devHalfStrokeSize) {
423 if (!stroke_dev_half_size_supported(devHalfStrokeSize)) {
426 return Helper::FactoryHelper<AAStrokeRectOp>(context, std::move(
paint), viewMatrix,
427 devOutside, devInside, devHalfStrokeSize);
439 fRects.emplace_back(RectInfo{
color, devOutside, devOutside, devInside, devHalfStrokeSize,
false});
440 this->setBounds(devOutside, HasAABloat::kYes, IsHairline::kNo);
458 if (!compute_aa_rects(*context->
priv().
caps(),
460 &
info.fDevOutsideAssist,
467 &
info.fDevHalfStrokeSize)) {
470 if (!stroke_dev_half_size_supported(
info.fDevHalfStrokeSize)) {
473 return Helper::FactoryHelper<AAStrokeRectOp>(context, std::move(
paint), viewMatrix,
info,
478 const SkMatrix& viewMatrix,
const RectInfo& infoExceptColor,
bool isMiter)
482 fMiterStroke = isMiter;
483 RectInfo&
info = fRects.push_back(infoExceptColor);
486 this->setBounds(
info.fDevOutside, HasAABloat::kYes, IsHairline::kNo);
491 bounds.joinPossiblyEmptyRect(
info.fDevOutsideAssist);
492 this->setBounds(bounds, HasAABloat::kYes, IsHairline::kNo);
496 const char*
name()
const override {
return "AAStrokeRect"; }
506 FixedFunctionFlags fixedFunctionFlags()
const override {
return fHelper.
fixedFunctionFlags(); }
512 &fRects.back().fColor, &fWideColor);
516 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
518 bool compatibleWithCoverageAsAlpha(
bool usesMSAASurface)
const {
524 void onCreateProgramInfo(
const GrCaps*,
527 bool usesMSAASurface,
536#if defined(GR_TEST_UTILS)
537 SkString onDumpInfo()
const override {
539 for (
const auto&
info : fRects) {
541 "Color: 0x%08x, ORect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
542 "AssistORect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
543 "IRect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], Degen: %d",
544 info.fColor.toBytes_RGBA(),
info.fDevOutside.fLeft,
info.fDevOutside.fTop,
545 info.fDevOutside.fRight,
info.fDevOutside.fBottom,
info.fDevOutsideAssist.fLeft,
546 info.fDevOutsideAssist.fTop,
info.fDevOutsideAssist.fRight,
547 info.fDevOutsideAssist.fBottom,
info.fDevInside.fLeft,
info.fDevInside.fTop,
548 info.fDevInside.fRight,
info.fDevInside.fBottom,
info.fDegenerate);
550 string += fHelper.dumpInfo();
555 static const int kMiterIndexCnt = 3 * 24;
556 static const int kMiterVertexCnt = 16;
557 static const int kNumMiterRectsInIndexBuffer = 256;
559 static const int kBevelIndexCnt = 48 + 36 + 24;
560 static const int kBevelVertexCnt = 24;
561 static const int kNumBevelRectsInIndexBuffer = 256;
566 bool miterStroke()
const {
return fMiterStroke; }
570 void generateAAStrokeRectGeometry(VertexWriter& vertices,
574 const SkRect& devOutsideAssist,
579 bool usesMSAASurface)
const;
592void AAStrokeRectOp::onCreateProgramInfo(
const GrCaps* caps,
595 bool usesMSAASurface,
604 this->compatibleWithCoverageAsAlpha(usesMSAASurface),
606 fHelper.usesLocalCoords(),
609 SkDebugf(
"Couldn't create GrGeometryProcessor\n");
613 fProgramInfo = fHelper.createProgramInfo(caps,
617 std::move(appliedClip),
621 renderPassXferBarriers,
628 this->createProgramInfo(
target);
634 int innerVertexNum = 4;
635 int outerVertexNum = this->miterStroke() ? 4 : 8;
636 int verticesPerInstance = (outerVertexNum + innerVertexNum) * 2;
637 int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt;
638 int instanceCount = fRects.size();
639 int maxQuads = this->miterStroke() ? kNumMiterRectsInIndexBuffer : kNumBevelRectsInIndexBuffer;
644 SkDebugf(
"Could not allocate indices\n");
649 verticesPerInstance, indicesPerInstance, instanceCount, maxQuads);
650 VertexWriter vertices{ helper.vertices() };
652 SkDebugf(
"Could not allocate vertices\n");
656 for (
int i = 0; i < instanceCount; i++) {
657 const RectInfo&
info = fRects[i];
658 this->generateAAStrokeRectGeometry(vertices,
662 info.fDevOutsideAssist,
666 info.fDevHalfStrokeSize,
667 target->usesMSAASurface());
669 fMesh = helper.mesh();
673 if (!fProgramInfo || !fMesh) {
686 static const uint16_t gMiterIndices[] = {
687 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
688 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
689 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
690 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
692 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
693 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
694 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
695 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
697 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
698 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
699 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
700 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
703 static_assert(std::size(gMiterIndices) == kMiterIndexCnt);
706 gMiterIndices, kMiterIndexCnt, kNumMiterRectsInIndexBuffer, kMiterVertexCnt,
707 gMiterIndexBufferKey);
739 static const uint16_t gBevelIndices[] = {
741 0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
742 1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
743 5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
744 6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
745 2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
746 3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
747 7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
748 4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
751 0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
753 5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
754 6 + 8, 2 + 8, 10 + 8,
755 2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
756 3 + 8, 7 + 8, 11 + 8,
757 7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
761 0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
762 1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
763 2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
764 3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
767 static_assert(std::size(gBevelIndices) == kBevelIndexCnt);
771 gBevelIndices, kBevelIndexCnt, kNumBevelRectsInIndexBuffer, kBevelVertexCnt,
772 gBevelIndexBufferKey);
778 AAStrokeRectOp* that = t->
cast<AAStrokeRectOp>();
780 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
781 return CombineResult::kCannotCombine;
785 if (this->miterStroke() != that->miterStroke()) {
786 return CombineResult::kCannotCombine;
791 if (fHelper.usesLocalCoords() &&
794 return CombineResult::kCannotCombine;
797 fRects.push_back_n(that->fRects.size(), that->fRects.begin());
798 fWideColor |= that->fWideColor;
799 return CombineResult::kMerged;
802void AAStrokeRectOp::generateAAStrokeRectGeometry(VertexWriter& vertices,
806 const SkRect& devOutsideAssist,
811 bool usesMSAASurface)
const {
819 SkASSERT(stroke_dev_half_size_supported(devHalfStrokeSize));
825 bool tweakAlphaForCoverage = this->compatibleWithCoverageAsAlpha(usesMSAASurface);
827 auto maybe_coverage = [tweakAlphaForCoverage](
float coverage) {
832 float inset = std::min(0.5f, std::min(devHalfStrokeSize.
fX, devHalfStrokeSize.
fY));
833 float innerCoverage = 1;
842 float outerCoverage = 0;
845 float interiorOutset =
outset;
846 float interiorCoverage = outerCoverage;
848 if (usesMSAASurface) {
853 outerCoverage -= msaaExtraBloat;
855 float insetExtraBloat =
856 std::min(
inset + msaaExtraBloat,
857 std::min(devHalfStrokeSize.
fX, devHalfStrokeSize.
fY)) -
inset;
858 inset += insetExtraBloat;
859 innerCoverage += insetExtraBloat;
861 float interiorExtraBloat =
862 std::min(interiorOutset + msaaExtraBloat,
863 std::min(devInside.
width(), devInside.
height()) / 2) - interiorOutset;
864 interiorOutset += interiorExtraBloat;
865 interiorCoverage -= interiorExtraBloat;
868 VertexColor innerColor(tweakAlphaForCoverage ?
color * innerCoverage :
color, wideColor);
872 vertices.writeQuad(inset_fan(devOutside, -
outset, -
outset),
874 maybe_coverage(outerCoverage));
878 vertices.writeQuad(inset_fan(devOutsideAssist, -
outset, -
outset),
880 maybe_coverage(outerCoverage));
884 vertices.writeQuad(inset_fan(devOutside,
inset,
inset),
886 maybe_coverage(innerCoverage));
890 vertices.writeQuad(inset_fan(devOutsideAssist,
inset,
inset),
892 maybe_coverage(innerCoverage));
897 vertices.writeQuad(inset_fan(devInside, -
inset, -
inset),
899 maybe_coverage(innerCoverage));
902 SkRect interiorAABoundary = devInside.
makeInset(interiorOutset, interiorOutset);
903 float coverageBackset = 0;
904 if (interiorAABoundary.
fLeft > interiorAABoundary.
fRight) {
906 (interiorAABoundary.
fLeft - interiorAABoundary.
fRight) / (interiorOutset * 2);
909 if (interiorAABoundary.
fTop > interiorAABoundary.
fBottom) {
910 coverageBackset = std::max(
911 (interiorAABoundary.
fTop - interiorAABoundary.
fBottom) / (interiorOutset * 2),
915 if (coverageBackset > 0) {
919 interiorCoverage += interiorCoverage * (1 - coverageBackset) +
920 innerCoverage * coverageBackset;
922 VertexColor interiorColor(tweakAlphaForCoverage ?
color * interiorCoverage :
color,
926 maybe_coverage(interiorCoverage));
933 maybe_coverage(innerCoverage));
938 maybe_coverage(innerCoverage));
952 return AAStrokeRectOp::Make(context, std::move(
paint), viewMatrix, rect, stroke);
954 return NonAAStrokeRectOp::Make(context, std::move(
paint), viewMatrix, rect, stroke, aaType);
963 SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty());
988 return AAStrokeRectOp::Make(context, std::move(
paint), viewMatrix, devOutside,