Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | List of all members
CircleOp Class Referencefinal
Inheritance diagram for CircleOp:
GrMeshDrawOp GrDrawOp GrOp SkNoncopyable

Classes

struct  ArcParams
 

Public Member Functions

 CircleOp (GrProcessorSet *processorSet, const SkPMColor4f &color, const SkMatrix &viewMatrix, SkPoint center, SkScalar radius, const GrStyle &style, const ArcParams *arcParams)
 
const char * name () const override
 
void visitProxies (const GrVisitProxyFunc &func) const override
 
GrProcessorSet::Analysis finalize (const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
 
FixedFunctionFlags fixedFunctionFlags () const override
 
- Public Member Functions inherited from GrDrawOp
 GrDrawOp (uint32_t classID)
 
virtual bool usesMSAA () const
 
virtual ClipResult clipToShape (skgpu::ganesh::SurfaceDrawContext *, SkClipOp, const SkMatrix &, const GrShape &, GrAA)
 
virtual GrProcessorSet::Analysis finalize (const GrCaps &, const GrAppliedClip *, GrClampType)=0
 
virtual bool usesStencil () const
 
- Public Member Functions inherited from GrOp
virtual ~GrOp ()=default
 
virtual const char * name () const =0
 
virtual void visitProxies (const GrVisitProxyFunc &) const
 
CombineResult combineIfPossible (GrOp *that, SkArenaAlloc *alloc, const GrCaps &caps)
 
const SkRectbounds () const
 
void setClippedBounds (const SkRect &clippedBounds)
 
bool hasAABloat () const
 
bool hasZeroArea () const
 
void operator delete (void *p)
 
template<typename T >
const Tcast () const
 
template<typename T >
Tcast ()
 
uint32_t classID () const
 
uint32_t uniqueID () const
 
void prePrepare (GrRecordingContext *context, const GrSurfaceProxyView &dstView, GrAppliedClip *clip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
 
void prepare (GrOpFlushState *state)
 
void execute (GrOpFlushState *state, const SkRect &chainBounds)
 
void chainConcat (GrOp::Owner)
 
bool isChainHead () const
 
bool isChainTail () const
 
GrOpnextInChain () const
 
GrOpprevInChain () const
 
GrOp::Owner cutChain ()
 
void setBounds (const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
 
void setTransformedBounds (const SkRect &srcBounds, const SkMatrix &m, HasAABloat aabloat, IsHairline zeroArea)
 
void makeFullScreen (GrSurfaceProxy *proxy)
 

Static Public Member Functions

static GrOp::Owner Make (GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, SkPoint center, SkScalar radius, const GrStyle &style, const ArcParams *arcParams=nullptr)
 
- Static Public Member Functions inherited from GrMeshDrawOp
static bool CanUpgradeAAOnMerge (GrAAType aa1, GrAAType aa2)
 
- Static Public Member Functions inherited from GrOp
template<typename Op , typename... Args>
static Owner Make (GrRecordingContext *context, Args &&... args)
 
template<typename Op , typename... Args>
static Owner MakeWithProcessorSet (GrRecordingContext *context, const SkPMColor4f &color, GrPaint &&paint, Args &&... args)
 
template<typename Op , typename... Args>
static Owner MakeWithExtraMemory (GrRecordingContext *context, size_t extraSize, Args &&... args)
 
static uint32_t GenOpClassID ()
 

Additional Inherited Members

- Public Types inherited from GrDrawOp
enum class  ClipResult { kFail , kClippedGeometrically , kClippedInShader , kClippedOut }
 
- Public Types inherited from GrOp
enum class  CombineResult { kMerged , kMayChain , kCannotCombine }
 
enum class  HasAABloat : bool { kNo = false , kYes = true }
 
enum class  IsHairline : bool { kNo = false , kYes = true }
 
using Owner = std::unique_ptr< GrOp >
 
- Protected Types inherited from GrDrawOp
enum class  FixedFunctionFlags : uint32_t { kNone = 0x0 , kUsesHWAA = 0x1 , kUsesStencil = 0x2 }
 
- Protected Member Functions inherited from GrMeshDrawOp
 GrMeshDrawOp (uint32_t classID)
 
void createProgramInfo (const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
 
void createProgramInfo (GrMeshDrawTarget *)
 
virtual void onPrePrepareDraws (GrRecordingContext *, const GrSurfaceProxyView &writeView, GrAppliedClip *, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
 
- Protected Member Functions inherited from GrDrawOp
 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS (FixedFunctionFlags)
 
virtual FixedFunctionFlags fixedFunctionFlags () const
 
- Static Protected Member Functions inherited from GrMeshDrawOp
static bool CombinedQuadCountWillOverflow (GrAAType aaType, bool willBeUpgradedToAA, int combinedQuadCount)
 

Detailed Description

Definition at line 985 of file GrOvalOpFactory.cpp.

Constructor & Destructor Documentation

◆ CircleOp()

CircleOp::CircleOp ( GrProcessorSet processorSet,
const SkPMColor4f color,
const SkMatrix viewMatrix,
SkPoint  center,
SkScalar  radius,
const GrStyle style,
const ArcParams arcParams 
)
inline

Definition at line 1041 of file GrOvalOpFactory.cpp.

1044 : GrMeshDrawOp(ClassID())
1045 , fHelper(processorSet, GrAAType::kCoverage) {
1046 const SkStrokeRec& stroke = style.strokeRec();
1047 SkStrokeRec::Style recStyle = stroke.getStyle();
1048
1049 fRoundCaps = false;
1050
1051 viewMatrix.mapPoints(&center, 1);
1052 radius = viewMatrix.mapRadius(radius);
1053 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth());
1054
1055 bool isStrokeOnly =
1057 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == recStyle;
1058
1059 SkScalar innerRadius = -SK_ScalarHalf;
1060 SkScalar outerRadius = radius;
1061 SkScalar halfWidth = 0;
1062 if (hasStroke) {
1064 halfWidth = SK_ScalarHalf;
1065 } else {
1066 halfWidth = SkScalarHalf(strokeWidth);
1067 }
1068
1069 outerRadius += halfWidth;
1070 if (isStrokeOnly) {
1071 innerRadius = radius - halfWidth;
1072 }
1073 }
1074
1075 // The radii are outset for two reasons. First, it allows the shader to simply perform
1076 // simpler computation because the computed alpha is zero, rather than 50%, at the radius.
1077 // Second, the outer radius is used to compute the verts of the bounding box that is
1078 // rendered and the outset ensures the box will cover all partially covered by the circle.
1079 outerRadius += SK_ScalarHalf;
1080 innerRadius -= SK_ScalarHalf;
1081 bool stroked = isStrokeOnly && innerRadius > 0.0f;
1082 fViewMatrixIfUsingLocalCoords = viewMatrix;
1083
1084 // This makes every point fully inside the intersection plane.
1085 static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f};
1086 // This makes every point fully outside the union plane.
1087 static constexpr SkScalar kUnusedUnionPlane[] = {0.f, 0.f, 0.f};
1088 static constexpr SkPoint kUnusedRoundCaps[] = {{1e10f, 1e10f}, {1e10f, 1e10f}};
1089 SkRect devBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
1090 center.fX + outerRadius, center.fY + outerRadius);
1091 if (arcParams) {
1092 // The shader operates in a space where the circle is translated to be centered at the
1093 // origin. Here we compute points on the unit circle at the starting and ending angles.
1094 SkPoint startPoint, stopPoint;
1095 startPoint.fY = SkScalarSin(arcParams->fStartAngleRadians);
1096 startPoint.fX = SkScalarCos(arcParams->fStartAngleRadians);
1097 SkScalar endAngle = arcParams->fStartAngleRadians + arcParams->fSweepAngleRadians;
1098 stopPoint.fY = SkScalarSin(endAngle);
1099 stopPoint.fX = SkScalarCos(endAngle);
1100
1101 // Adjust the start and end points based on the view matrix (to handle rotated arcs)
1102 startPoint = viewMatrix.mapVector(startPoint.fX, startPoint.fY);
1103 stopPoint = viewMatrix.mapVector(stopPoint.fX, stopPoint.fY);
1104 startPoint.normalize();
1105 stopPoint.normalize();
1106
1107 // We know the matrix is a similarity here. Detect mirroring which will affect how we
1108 // should orient the clip planes for arcs.
1109 SkASSERT(viewMatrix.isSimilarity());
1110 auto upperLeftDet = viewMatrix.getScaleX()*viewMatrix.getScaleY() -
1111 viewMatrix.getSkewX() *viewMatrix.getSkewY();
1112 if (upperLeftDet < 0) {
1113 std::swap(startPoint, stopPoint);
1114 }
1115
1116 fRoundCaps = style.strokeRec().getWidth() > 0 &&
1118 SkPoint roundCaps[2];
1119 if (fRoundCaps) {
1120 // Compute the cap center points in the normalized space.
1121 SkScalar midRadius = (innerRadius + outerRadius) / (2 * outerRadius);
1122 roundCaps[0] = startPoint * midRadius;
1123 roundCaps[1] = stopPoint * midRadius;
1124 } else {
1125 roundCaps[0] = kUnusedRoundCaps[0];
1126 roundCaps[1] = kUnusedRoundCaps[1];
1127 }
1128
1129 // Like a fill without useCenter, butt-cap stroke can be implemented by clipping against
1130 // radial lines. We treat round caps the same way, but tack coverage of circles at the
1131 // center of the butts.
1132 // However, in both cases we have to be careful about the half-circle.
1133 // case. In that case the two radial lines are equal and so that edge gets clipped
1134 // twice. Since the shared edge goes through the center we fall back on the !useCenter
1135 // case.
1136 auto absSweep = SkScalarAbs(arcParams->fSweepAngleRadians);
1137 bool useCenter = (arcParams->fUseCenter || isStrokeOnly) &&
1138 !SkScalarNearlyEqual(absSweep, SK_ScalarPI);
1139 if (useCenter) {
1140 SkVector norm0 = {startPoint.fY, -startPoint.fX};
1141 SkVector norm1 = {stopPoint.fY, -stopPoint.fX};
1142 // This ensures that norm0 is always the clockwise plane, and norm1 is CCW.
1143 if (arcParams->fSweepAngleRadians < 0) {
1144 std::swap(norm0, norm1);
1145 }
1146 norm0.negate();
1147 fClipPlane = true;
1148 if (absSweep > SK_ScalarPI) {
1149 fCircles.emplace_back(Circle{
1150 color,
1151 innerRadius,
1152 outerRadius,
1153 {norm0.fX, norm0.fY, 0.5f},
1154 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
1155 {norm1.fX, norm1.fY, 0.5f},
1156 {roundCaps[0], roundCaps[1]},
1157 devBounds,
1158 stroked});
1159 fClipPlaneIsect = false;
1160 fClipPlaneUnion = true;
1161 } else {
1162 fCircles.emplace_back(Circle{
1163 color,
1164 innerRadius,
1165 outerRadius,
1166 {norm0.fX, norm0.fY, 0.5f},
1167 {norm1.fX, norm1.fY, 0.5f},
1168 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
1169 {roundCaps[0], roundCaps[1]},
1170 devBounds,
1171 stroked});
1172 fClipPlaneIsect = true;
1173 fClipPlaneUnion = false;
1174 }
1175 } else {
1176 // We clip to a secant of the original circle.
1177 startPoint.scale(radius);
1178 stopPoint.scale(radius);
1179 SkVector norm = {startPoint.fY - stopPoint.fY, stopPoint.fX - startPoint.fX};
1180 norm.normalize();
1181 if (arcParams->fSweepAngleRadians > 0) {
1182 norm.negate();
1183 }
1184 SkScalar d = -norm.dot(startPoint) + 0.5f;
1185
1186 fCircles.emplace_back(
1187 Circle{color,
1188 innerRadius,
1189 outerRadius,
1190 {norm.fX, norm.fY, d},
1191 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
1192 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
1193 {roundCaps[0], roundCaps[1]},
1194 devBounds,
1195 stroked});
1196 fClipPlane = true;
1197 fClipPlaneIsect = false;
1198 fClipPlaneUnion = false;
1199 }
1200 } else {
1201 fCircles.emplace_back(
1202 Circle{color,
1203 innerRadius,
1204 outerRadius,
1205 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
1206 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]},
1207 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]},
1208 {kUnusedRoundCaps[0], kUnusedRoundCaps[1]},
1209 devBounds,
1210 stroked});
1211 fClipPlane = false;
1212 fClipPlaneIsect = false;
1213 fClipPlaneUnion = false;
1214 }
1215 // Use the original radius and stroke radius for the bounds so that it does not include the
1216 // AA bloat.
1217 radius += halfWidth;
1218 this->setBounds(
1219 {center.fX - radius, center.fY - radius, center.fX + radius, center.fY + radius},
1221 fVertCount = circle_type_to_vert_count(stroked);
1222 fIndexCount = circle_type_to_index_count(stroked);
1223 fAllFill = !stroked;
1224 }
static const int strokeWidth
Definition: BlurTest.cpp:60
static int circle_type_to_index_count(bool stroked)
static int circle_type_to_vert_count(bool stroked)
#define SkASSERT(cond)
Definition: SkAssert.h:116
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
#define SkScalarSin(radians)
Definition: SkScalar.h:45
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107
#define SkScalarHalf(a)
Definition: SkScalar.h:75
#define SK_ScalarHalf
Definition: SkScalar.h:19
#define SkScalarCos(radians)
Definition: SkScalar.h:46
#define SkScalarAbs(x)
Definition: SkScalar.h:39
#define SK_ScalarPI
Definition: SkScalar.h:21
static SkScalar center(float pos0, float pos1)
GrMeshDrawOp(uint32_t classID)
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
Definition: GrOp.h:279
const SkStrokeRec & strokeRec() const
Definition: GrStyle.h:140
SkScalar mapRadius(SkScalar radius) const
Definition: SkMatrix.cpp:1170
SkScalar getSkewY() const
Definition: SkMatrix.h:430
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
SkScalar getSkewX() const
Definition: SkMatrix.h:438
SkScalar getScaleX() const
Definition: SkMatrix.h:415
SkScalar getScaleY() const
Definition: SkMatrix.h:422
bool isSimilarity(SkScalar tol=SK_ScalarNearlyZero) const
Definition: SkMatrix.cpp:180
void mapVector(SkScalar dx, SkScalar dy, SkVector *result) const
Definition: SkMatrix.h:1524
@ kRound_Cap
adds circle
Definition: SkPaint.h:335
@ kStrokeAndFill_Style
Definition: SkStrokeRec.h:36
SkScalar getWidth() const
Definition: SkStrokeRec.h:42
SkPaint::Cap getCap() const
Definition: SkStrokeRec.h:44
T & emplace_back(Args &&... args)
Definition: SkTArray.h:248
DlColor color
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
float SkScalar
Definition: extension.cpp:12
void negate()
Definition: SkPoint_impl.h:357
float fX
x-axis value
Definition: SkPoint_impl.h:164
float dot(const SkVector &vec) const
Definition: SkPoint_impl.h:554
void scale(float scale, SkPoint *dst) const
Definition: SkPoint.cpp:17
float fY
y-axis value
Definition: SkPoint_impl.h:165
bool normalize()
Definition: SkPoint.cpp:22
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646

Member Function Documentation

◆ finalize()

GrProcessorSet::Analysis CircleOp::finalize ( const GrCaps ,
const GrAppliedClip ,
GrClampType   
)
inlineoverridevirtual

This is called after the GrAppliedClip has been computed and just prior to recording the op or combining it with a previously recorded op. The op should convert any proxies or resources it owns to "pending io" status so that resource allocation can be more optimal. Additionally, at this time the op must report whether a copy of the destination (or destination texture itself) needs to be provided to the GrXferProcessor when this op executes.

Implements GrDrawOp.

Definition at line 1236 of file GrOvalOpFactory.cpp.

1237 {
1238 SkPMColor4f* color = &fCircles.front().fColor;
1239 return fHelper.finalizeProcessors(caps, clip, clampType,
1241 &fWideColor);
1242 }
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)

◆ fixedFunctionFlags()

FixedFunctionFlags CircleOp::fixedFunctionFlags ( ) const
inlineoverridevirtual

Reimplemented from GrDrawOp.

Definition at line 1244 of file GrOvalOpFactory.cpp.

1244{ return fHelper.fixedFunctionFlags(); }
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const

◆ Make()

static GrOp::Owner CircleOp::Make ( GrRecordingContext context,
GrPaint &&  paint,
const SkMatrix viewMatrix,
SkPoint  center,
SkScalar  radius,
const GrStyle style,
const ArcParams arcParams = nullptr 
)
inlinestatic

Definition at line 999 of file GrOvalOpFactory.cpp.

1005 {
1006 SkASSERT(circle_stays_circle(viewMatrix));
1007 if (style.hasPathEffect()) {
1008 return nullptr;
1009 }
1010 const SkStrokeRec& stroke = style.strokeRec();
1011 SkStrokeRec::Style recStyle = stroke.getStyle();
1012 if (arcParams) {
1013 // Arc support depends on the style.
1014 switch (recStyle) {
1016 // This produces a strange result that this op doesn't implement.
1017 return nullptr;
1019 // This supports all fills.
1020 break;
1022 // Strokes that don't use the center point are supported with butt and round
1023 // caps.
1024 if (arcParams->fUseCenter || stroke.getCap() == SkPaint::kSquare_Cap) {
1025 return nullptr;
1026 }
1027 break;
1029 // Hairline only supports butt cap. Round caps could be emulated by slightly
1030 // extending the angle range if we ever care to.
1031 if (arcParams->fUseCenter || stroke.getCap() != SkPaint::kButt_Cap) {
1032 return nullptr;
1033 }
1034 break;
1035 }
1036 }
1037 return Helper::FactoryHelper<CircleOp>(context, std::move(paint), viewMatrix, center,
1038 radius, style, arcParams);
1039 }
bool hasPathEffect() const
Definition: GrStyle.h:122
@ kButt_Cap
no stroke extension
Definition: SkPaint.h:334
@ kSquare_Cap
adds square
Definition: SkPaint.h:336
const Paint & paint
Definition: color_source.cc:38

◆ name()

const char * CircleOp::name ( ) const
inlineoverridevirtual

Implements GrOp.

Definition at line 1226 of file GrOvalOpFactory.cpp.

1226{ return "CircleOp"; }

◆ visitProxies()

void CircleOp::visitProxies ( const GrVisitProxyFunc func) const
inlineoverridevirtual

Reimplemented from GrOp.

Definition at line 1228 of file GrOvalOpFactory.cpp.

1228 {
1229 if (fProgramInfo) {
1230 fProgramInfo->visitFPProxies(func);
1231 } else {
1232 fHelper.visitProxies(func);
1233 }
1234 }
void visitFPProxies(const GrVisitProxyFunc &func) const
Definition: GrProgramInfo.h:64
void visitProxies(const GrVisitProxyFunc &func) const

The documentation for this class was generated from the following file: