77 verts[4].
set(
rect.fRight - rad,
rect.fBottom - rad);
78 verts[5].
set(
rect.fRight + 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) {
143 fStrokeWidth =
stroke.getWidth();
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;
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;
336 if (!devRect.
intersect(visibilityBounds)) {
340 *devOutside = devRect;
341 *devOutsideAssist = devRect;
342 *devInside = devRect;
344 devOutside->
outset(rx, ry);
345 devInside->
inset(rx, ry);
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;
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) {
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 =
858 inset += insetExtraBloat;
859 innerCoverage += insetExtraBloat;
861 float interiorExtraBloat =
862 std::min(interiorOutset + msaaExtraBloat,
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) {
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));
963 SkASSERT(!rects[0].isEmpty() && !rects[1].isEmpty());
994#if defined(GR_TEST_UTILS)
998GR_DRAW_OP_TEST_DEFINE(NonAAStrokeRectOp) {
999 SkMatrix viewMatrix = GrTest::TestMatrix(random);
1008 if (numSamples > 1) {
1012 viewMatrix,
rect, strokeRec,
1016GR_DRAW_OP_TEST_DEFINE(AAStrokeRectOp) {
1017 bool miterStroke = random->nextBool();
static const int strokeWidth
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#define DEFINE_OP_CLASS_ID
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
#define SKGPU_DEFINE_STATIC_UNIQUE_KEY(name)
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define INHERITED(method,...)
#define SkScalarFloorToScalar(x)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
SkVector fDevHalfStrokeSize
const GrCaps * caps() const
bool avoidLineDraws() const
bool reducedShaderMode() const
int maxRenderTargetSize() const
size_t vertexStride() const
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
std::unique_ptr< GrOp > Owner
const GrPipeline & pipeline() const
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
static GrQuad MakeFromRect(const SkRect &, const SkMatrix &)
GrRecordingContextPriv priv()
sk_sp< const GrGpuBuffer > findOrCreatePatternedIndexBuffer(const uint16_t *pattern, int patternSize, int reps, int vertCount, const skgpu::UniqueKey &key)
@ kSnapVerticesToPixelCenters
void visitProxies(const GrVisitProxyFunc &func) const
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const
bool usesLocalCoords() const
GrProgramInfo * createProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
bool compatibleWithCoverageAsAlpha() const
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
void mapVectors(SkVector dst[], const SkVector src[], int count) const
bool rectStaysRect() const
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
@ kButt_Cap
no stroke extension
void setStyle(Style style)
@ kStroke_Style
set to stroke geometry
void setStrokeJoin(Join join)
@ kMiter_Join
extends to miter limit
@ kBevel_Join
connects outside edges
void setStrokeWidth(SkScalar width)
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
static GrOp::Owner Make(GrRecordingContext *, GrPaint &&, GrAAType, DrawQuad *, const GrUserStencilSettings *=nullptr, InputFlags=InputFlags::kNone)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
GrGeometryProcessor * Make(SkArenaAlloc *, const Color &, const Coverage &, const LocalCoords &, const SkMatrix &viewMatrix)
GrGeometryProcessor * MakeForDeviceSpace(SkArenaAlloc *, const Color &, const Coverage &, const LocalCoords &, const SkMatrix &viewMatrix)
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
sk_sp< const GrBuffer > GetIndexBuffer(GrMeshDrawTarget *target, IndexBufferOption indexBufferOption)
GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, GrAAType aaType, const SkMatrix &viewMatrix, const SkRect &rect, const SkStrokeRec &stroke)
GrOp::Owner MakeNested(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, const SkRect rects[2])
SKGPU_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey)
static SkRect inset(const SkRect &r)
void set(sk_sp< const GrBuffer > vertexBuffer, int vertexCount, int baseVertex)
void setAbs(const SkPoint &pt)
void set(float x, float y)
SkScalar fBottom
larger y-axis bounds
void inset(float dx, float dy)
bool intersect(const SkRect &r)
SkScalar fLeft
smaller x-axis bounds
void outset(float dx, float dy)
SkRect makeOutset(float dx, float dy) const
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
SkRect makeInset(float dx, float dy) const
SkScalar fRight
larger x-axis bounds
constexpr float centerX() const
constexpr float height() const
constexpr float centerY() const
constexpr float width() const
static constexpr SkRect MakeWH(float w, float h)
SkScalar fTop
smaller y-axis bounds
static TriFan< float > TriFanFromRect(const SkRect &r)
static Conditional< T > If(bool condition, const T &value)