38#ifndef SK_ENABLE_OPTIMIZE_SIZE
45static inline bool circle_stays_circle(
const SkMatrix&
m) {
return m.isSimilarity(); }
48static inline VertexWriter::TriStrip<float> origin_centered_tri_strip(
float x,
float y) {
49 return VertexWriter::TriStrip<float>{ -
x, -
y,
x,
y };
78 bool isectPlane,
bool unionPlane,
bool roundCaps,
79 bool wideColor,
const SkMatrix& localMatrix) {
80 return arena->
make([&](
void* ptr) {
82 roundCaps, wideColor, localMatrix);
86 const char*
name()
const override {
return "CircleGeometryProcessor"; }
89 b->addBool(fStroke,
"stroked" );
100 return std::make_unique<Impl>();
105 bool roundCaps,
bool wideColor,
const SkMatrix& localMatrix)
107 , fLocalMatrix(localMatrix)
144 void onEmitCode(EmitArgs&
args, GrGPArgs* gpArgs)
override {
153 fragBuilder->
codeAppend(
"float4 circleEdge;");
173 fragBuilder->
codeAppend(
"float4 roundCapCenters;");
176 varyingHandler->
addVarying(
"capRadius", &capRadius,
180 vertBuilder->codeAppendf(
"%s = (1.0 - %s.w) / 2.0;", capRadius.vsOut(),
181 cgp.fInCircleEdge.
name());
196 &fLocalMatrixUniform);
198 fragBuilder->
codeAppend(
"float d = length(circleEdge.xy);");
199 fragBuilder->
codeAppend(
"half distanceToOuterEdge = half(circleEdge.z * (1.0 - d));");
200 fragBuilder->
codeAppend(
"half edgeAlpha = saturate(distanceToOuterEdge);");
203 "half distanceToInnerEdge = half(circleEdge.z * (d - circleEdge.w));");
204 fragBuilder->
codeAppend(
"half innerAlpha = saturate(distanceToInnerEdge);");
205 fragBuilder->
codeAppend(
"edgeAlpha *= innerAlpha;");
210 "half clip = half(saturate(circleEdge.z * dot(circleEdge.xy, "
211 "clipPlane.xy) + clipPlane.z));");
214 "clip *= half(saturate(circleEdge.z * dot(circleEdge.xy, "
215 "isectPlane.xy) + isectPlane.z));");
219 "clip = saturate(clip + half(saturate(circleEdge.z * dot(circleEdge.xy,"
220 " unionPlane.xy) + unionPlane.z)));");
222 fragBuilder->
codeAppend(
"edgeAlpha *= clip;");
228 "half dcap1 = half(circleEdge.z * (%s - length(circleEdge.xy - "
229 "roundCapCenters.xy)));"
230 "half dcap2 = half(circleEdge.z * (%s - length(circleEdge.xy - "
231 "roundCapCenters.zw)));"
232 "half capAlpha = (1 - clip) * (max(dcap1, 0) + max(dcap2, 0));"
233 "edgeAlpha = min(edgeAlpha + capAlpha, 1.0);",
234 capRadius.fsIn(), capRadius.fsIn());
237 fragBuilder->
codeAppendf(
"half4 %s = half4(edgeAlpha);",
args.fOutputCoverage);
263#if defined(GR_TEST_UTILS)
265 bool stroke =
d->fRandom->nextBool();
266 bool roundCaps =
stroke ?
d->fRandom->nextBool() :
false;
267 bool wideColor =
d->fRandom->nextBool();
268 bool clipPlane =
d->fRandom->nextBool();
269 bool isectPlane =
d->fRandom->nextBool();
270 bool unionPlane =
d->fRandom->nextBool();
273 unionPlane, roundCaps, wideColor,
matrix);
281 return arena->
make([&](
void* ptr) {
288 const char*
name()
const override {
return "ButtCapDashedCircleGeometryProcessor"; }
297 return std::make_unique<Impl>();
303 , fLocalMatrix(localMatrix) {
324 void onEmitCode(EmitArgs&
args, GrGPArgs* gpArgs)
override {
334 fragBuilder->
codeAppend(
"float4 circleEdge;");
338 fragBuilder->
codeAppend(
"float4 dashParams;");
344 varyingHandler->
addVarying(
"wrapDashes", &wrapDashes,
347 varyingHandler->
addVarying(
"lastIntervalLength", &lastIntervalLength,
349 vertBuilder->codeAppendf(
"float4 dashParams = %s;", bcscgp.fInDashParams.
name());
366 vertBuilder->codeAppend(
370 "half lastIntervalLength = mod(6.28318530718, half(dashParams.y));"
372 "if (0 == lastIntervalLength) {"
373 "lastIntervalLength = half(dashParams.y);"
380 "if (-dashParams.w >= lastIntervalLength) {"
381 "offset = half(-dashParams.y);"
382 "} else if (dashParams.w > dashParams.y - lastIntervalLength) {"
383 "offset = half(dashParams.y);"
385 "wrapDashes.x = -lastIntervalLength + offset - dashParams.w;"
388 "wrapDashes.y = min(wrapDashes.x + dashParams.x, 0);"
393 "if (dashParams.w >= dashParams.x) {"
394 "offset = half(dashParams.y);"
395 "} else if (-dashParams.w > dashParams.y - dashParams.x) {"
396 "offset = half(-dashParams.y);"
398 "wrapDashes.z = lastIntervalLength + offset - dashParams.w;"
399 "wrapDashes.w = wrapDashes.z + dashParams.x;"
402 "wrapDashes.z = max(wrapDashes.z, lastIntervalLength);"
404 vertBuilder->codeAppendf(
"%s = half4(wrapDashes);", wrapDashes.vsOut());
405 vertBuilder->codeAppendf(
"%s = lastIntervalLength;", lastIntervalLength.vsOut());
406 fragBuilder->
codeAppendf(
"half4 wrapDashes = %s;", wrapDashes.fsIn());
407 fragBuilder->
codeAppendf(
"half lastIntervalLength = %s;", lastIntervalLength.fsIn());
424 &fLocalMatrixUniform);
432 {fnArgs, std::size(fnArgs)},
434 "angleToEdge = clamp(angleToEdge, -3.1415, 3.1415);"
435 "linearDist = diameter * sin(angleToEdge / 2);"
436 "return saturate(linearDist + 0.5);"
439 "float d = length(circleEdge.xy) * circleEdge.z;"
442 "half distanceToOuterEdge = half(circleEdge.z - d);"
443 "half edgeAlpha = saturate(distanceToOuterEdge);"
444 "half distanceToInnerEdge = half(d - circleEdge.z * circleEdge.w);"
445 "half innerAlpha = saturate(distanceToInnerEdge);"
446 "edgeAlpha *= innerAlpha;"
448 "half angleFromStart = half(atan(circleEdge.y, circleEdge.x) - dashParams.z);"
449 "angleFromStart = mod(angleFromStart, 6.28318530718);"
450 "float x = mod(angleFromStart, dashParams.y);"
453 "half2 currDash = half2(half(-dashParams.w), half(dashParams.x) -"
454 "half(dashParams.w));"
455 "half2 nextDash = half2(half(dashParams.y) - half(dashParams.w),"
456 "half(dashParams.y) + half(dashParams.x) -"
457 "half(dashParams.w));"
458 "half2 prevDash = half2(half(-dashParams.y) - half(dashParams.w),"
459 "half(-dashParams.y) + half(dashParams.x) -"
460 "half(dashParams.w));"
461 "const half kDashBoundsEpsilon = 0.01;"
462 "half dashAlpha = 0;"
465 "if (angleFromStart - x + dashParams.y >= 6.28318530718 + kDashBoundsEpsilon) {"
466 "dashAlpha += half(%s(x - wrapDashes.z, d) * %s(wrapDashes.w - x, d));"
467 "currDash.y = min(currDash.y, lastIntervalLength);"
468 "if (nextDash.x >= lastIntervalLength) {"
470 "nextDash.xy = half2(1000);"
473 "nextDash.y = min(nextDash.y, lastIntervalLength);"
478 "if (angleFromStart - x - dashParams.y < -kDashBoundsEpsilon) {"
479 "dashAlpha += half(%s(x - wrapDashes.x, d) * %s(wrapDashes.y - x, d));"
480 "currDash.x = max(currDash.x, 0);"
481 "if (prevDash.y <= 0) {"
483 "prevDash.xy = half2(1000);"
486 "prevDash.x = max(prevDash.x, 0);"
491 "dashAlpha += half(%s(x - currDash.x, d) * %s(currDash.y - x, d));"
492 "dashAlpha += half(%s(x - nextDash.x, d) * %s(nextDash.y - x, d));"
493 "dashAlpha += half(%s(x - prevDash.x, d) * %s(prevDash.y - x, d));"
494 "dashAlpha = min(dashAlpha, 1);"
495 "edgeAlpha *= dashAlpha;"
498 fragBuilder->
codeAppendf(
"half4 %s = half4(edgeAlpha);",
args.fOutputCoverage);
516#if defined(GR_TEST_UTILS)
518 bool wideColor =
d->fRandom->nextBool();
537 bool useScale,
const SkMatrix& localMatrix) {
538 return arena->
make([&](
void* ptr) {
545 const char*
name()
const override {
return "EllipseGeometryProcessor"; }
548 b->addBool(fStroke,
"stroked");
555 return std::make_unique<Impl>();
562 , fLocalMatrix(localMatrix)
564 , fUseScale(useScale) {
582 SetTransform(pdman, shaderCaps, fLocalMatrixUniform, egp.fLocalMatrix, &fLocalMatrix);
586 void onEmitCode(EmitArgs&
args, GrGPArgs* gpArgs)
override {
597 varyingHandler->
addVarying(
"EllipseOffsets", &ellipseOffsets);
598 vertBuilder->codeAppendf(
"%s = %s;", ellipseOffsets.vsOut(),
599 egp.fInEllipseOffset.
name());
602 varyingHandler->
addVarying(
"EllipseRadii", &ellipseRadii);
603 vertBuilder->codeAppendf(
"%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii.
name());
618 &fLocalMatrixUniform);
632 fragBuilder->
codeAppendf(
"float2 offset = %s.xy;", ellipseOffsets.fsIn());
634 fragBuilder->
codeAppendf(
"offset *= %s.xy;", ellipseRadii.fsIn());
636 fragBuilder->
codeAppend(
"float test = dot(offset, offset) - 1.0;");
638 fragBuilder->
codeAppendf(
"float2 grad = 2.0*offset*(%s.z*%s.xy);",
639 ellipseOffsets.fsIn(), ellipseRadii.fsIn());
641 fragBuilder->
codeAppendf(
"float2 grad = 2.0*offset*%s.xy;", ellipseRadii.fsIn());
643 fragBuilder->
codeAppend(
"float grad_dot = dot(grad, grad);");
646 if (
args.fShaderCaps->fFloatIs32Bits) {
647 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 1.1755e-38);");
649 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 6.1036e-5);");
652 fragBuilder->
codeAppendf(
"float invlen = %s.z*inversesqrt(grad_dot);",
653 ellipseOffsets.fsIn());
655 fragBuilder->
codeAppend(
"float invlen = inversesqrt(grad_dot);");
657 fragBuilder->
codeAppend(
"float edgeAlpha = saturate(0.5-test*invlen);");
661 fragBuilder->
codeAppendf(
"offset = %s.xy*%s.zw;", ellipseOffsets.fsIn(),
662 ellipseRadii.fsIn());
663 fragBuilder->
codeAppend(
"test = dot(offset, offset) - 1.0;");
665 fragBuilder->
codeAppendf(
"grad = 2.0*offset*(%s.z*%s.zw);",
666 ellipseOffsets.fsIn(), ellipseRadii.fsIn());
668 fragBuilder->
codeAppendf(
"grad = 2.0*offset*%s.zw;", ellipseRadii.fsIn());
670 fragBuilder->
codeAppend(
"grad_dot = dot(grad, grad);");
671 if (!
args.fShaderCaps->fFloatIs32Bits) {
672 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 6.1036e-5);");
675 fragBuilder->
codeAppendf(
"invlen = %s.z*inversesqrt(grad_dot);",
676 ellipseOffsets.fsIn());
678 fragBuilder->
codeAppend(
"invlen = inversesqrt(grad_dot);");
680 fragBuilder->
codeAppend(
"edgeAlpha *= saturate(0.5+test*invlen);");
683 fragBuilder->
codeAppendf(
"half4 %s = half4(half(edgeAlpha));",
args.fOutputCoverage);
708#if defined(GR_TEST_UTILS)
710 bool stroke =
d->fRandom->nextBool();
711 bool wideColor =
d->fRandom->nextBool();
712 bool useScale =
d->fRandom->nextBool();
735 return arena->
make([&](
void* ptr) {
742 const char*
name()
const override {
return "DIEllipseGeometryProcessor"; }
745 b->addBits(2,
static_cast<uint32_t
>(fStyle),
"style");
752 return std::make_unique<Impl>();
759 , fViewMatrix(viewMatrix)
760 , fUseScale(useScale)
782 SetTransform(pdman, shaderCaps, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix);
786 void onEmitCode(EmitArgs&
args, GrGPArgs* gpArgs)
override {
797 varyingHandler->
addVarying(
"EllipseOffsets0", &offsets0);
798 vertBuilder->codeAppendf(
"%s = %s;", offsets0.vsOut(), diegp.fInEllipseOffsets0.name());
801 varyingHandler->
addVarying(
"EllipseOffsets1", &offsets1);
802 vertBuilder->codeAppendf(
"%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1.name());
814 diegp.fInPosition.name(),
816 &fViewMatrixUniform);
817 gpArgs->fLocalCoordVar = diegp.fInPosition.asShaderVar();
820 fragBuilder->
codeAppendf(
"float2 scaledOffset = %s.xy;", offsets0.fsIn());
821 fragBuilder->
codeAppend(
"float test = dot(scaledOffset, scaledOffset) - 1.0;");
822 fragBuilder->
codeAppendf(
"float2 duvdx = dFdx(%s.xy);", offsets0.fsIn());
823 fragBuilder->
codeAppendf(
"float2 duvdy = dFdy(%s.xy);", offsets0.fsIn());
825 "float2 grad = float2(%s.x*duvdx.x + %s.y*duvdx.y,"
826 " %s.x*duvdy.x + %s.y*duvdy.y);",
827 offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn());
828 if (diegp.fUseScale) {
829 fragBuilder->
codeAppendf(
"grad *= %s.z;", offsets0.fsIn());
832 fragBuilder->
codeAppend(
"float grad_dot = 4.0*dot(grad, grad);");
834 if (
args.fShaderCaps->fFloatIs32Bits) {
835 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 1.1755e-38);");
837 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 6.1036e-5);");
839 fragBuilder->
codeAppend(
"float invlen = inversesqrt(grad_dot);");
840 if (diegp.fUseScale) {
841 fragBuilder->
codeAppendf(
"invlen *= %s.z;", offsets0.fsIn());
845 fragBuilder->
codeAppend(
"float edgeAlpha = saturate(1.0-test*invlen);");
846 fragBuilder->
codeAppend(
"edgeAlpha *= saturate(1.0+test*invlen);");
848 fragBuilder->
codeAppend(
"float edgeAlpha = saturate(0.5-test*invlen);");
853 fragBuilder->
codeAppendf(
"scaledOffset = %s.xy;", offsets1.fsIn());
854 fragBuilder->
codeAppend(
"test = dot(scaledOffset, scaledOffset) - 1.0;");
855 fragBuilder->
codeAppendf(
"duvdx = float2(dFdx(%s));", offsets1.fsIn());
856 fragBuilder->
codeAppendf(
"duvdy = float2(dFdy(%s));", offsets1.fsIn());
858 "grad = float2(%s.x*duvdx.x + %s.y*duvdx.y,"
859 " %s.x*duvdy.x + %s.y*duvdy.y);",
860 offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn());
861 if (diegp.fUseScale) {
862 fragBuilder->
codeAppendf(
"grad *= %s.z;", offsets0.fsIn());
864 fragBuilder->
codeAppend(
"grad_dot = 4.0*dot(grad, grad);");
865 if (!
args.fShaderCaps->fFloatIs32Bits) {
866 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 6.1036e-5);");
868 fragBuilder->
codeAppend(
"invlen = inversesqrt(grad_dot);");
869 if (diegp.fUseScale) {
870 fragBuilder->
codeAppendf(
"invlen *= %s.z;", offsets0.fsIn());
872 fragBuilder->
codeAppend(
"edgeAlpha *= saturate(0.5+test*invlen);");
875 fragBuilder->
codeAppendf(
"half4 %s = half4(half(edgeAlpha));",
args.fOutputCoverage);
898#if defined(GR_TEST_UTILS)
900 bool wideColor =
d->fRandom->nextBool();
901 bool useScale =
d->fRandom->nextBool();
1006 SkASSERT(circle_stays_circle(viewMatrix));
1037 return Helper::FactoryHelper<CircleOp>(context, std::move(
paint), viewMatrix,
center,
1038 radius, style, arcParams);
1069 outerRadius += halfWidth;
1071 innerRadius = radius - halfWidth;
1081 bool stroked = isStrokeOnly && innerRadius > 0.0f;
1082 fViewMatrixIfUsingLocalCoords = viewMatrix;
1085 static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f};
1087 static constexpr SkScalar kUnusedUnionPlane[] = {0.f, 0.f, 0.f};
1088 static constexpr SkPoint kUnusedRoundCaps[] = {{1e10f, 1e10f}, {1e10f, 1e10f}};
1094 SkPoint startPoint, stopPoint;
1102 startPoint = viewMatrix.
mapVector(startPoint.
fX, startPoint.
fY);
1103 stopPoint = viewMatrix.
mapVector(stopPoint.
fX, stopPoint.
fY);
1112 if (upperLeftDet < 0) {
1121 SkScalar midRadius = (innerRadius + outerRadius) / (2 * outerRadius);
1122 roundCaps[0] = startPoint * midRadius;
1123 roundCaps[1] = stopPoint * midRadius;
1125 roundCaps[0] = kUnusedRoundCaps[0];
1126 roundCaps[1] = kUnusedRoundCaps[1];
1137 bool useCenter = (arcParams->
fUseCenter || isStrokeOnly) &&
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]},
1159 fClipPlaneIsect =
false;
1160 fClipPlaneUnion =
true;
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]},
1172 fClipPlaneIsect =
true;
1173 fClipPlaneUnion =
false;
1177 startPoint.
scale(radius);
1178 stopPoint.
scale(radius);
1179 SkVector norm = {startPoint.
fY - stopPoint.
fY, stopPoint.
fX - startPoint.
fX};
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]},
1197 fClipPlaneIsect =
false;
1198 fClipPlaneUnion =
false;
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]},
1212 fClipPlaneIsect =
false;
1213 fClipPlaneUnion =
false;
1217 radius += halfWidth;
1223 fAllFill = !stroked;
1226 const char*
name()
const override {
return "CircleOp"; }
1247 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
1249 void onCreateProgramInfo(
const GrCaps* caps,
1252 bool usesMSAASurface,
1260 if (!fViewMatrixIfUsingLocalCoords.
invert(&localMatrix)) {
1265 fClipPlaneIsect, fClipPlaneUnion,
1266 fRoundCaps, fWideColor,
1273 std::move(appliedClip),
1277 renderPassXferBarriers,
1282 if (!fProgramInfo) {
1284 if (!fProgramInfo) {
1292 fVertCount, &vertexBuffer, &firstVertex);
1294 SkDebugf(
"Could not allocate vertices\n");
1300 uint16_t* indices =
target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
1302 SkDebugf(
"Could not allocate indices\n");
1306 int currStartVertex = 0;
1307 for (
const auto& circle : fCircles) {
1308 SkScalar innerRadius = circle.fInnerRadius;
1309 SkScalar outerRadius = circle.fOuterRadius;
1314 innerRadius = innerRadius / outerRadius;
1315 SkPoint radii = { outerRadius, innerRadius };
1322 if (!circle.fStroked && fClipPlane && fClipPlaneIsect &&
1323 (circle.fClipPlane[0] * circle.fIsectPlane[0] +
1324 circle.fClipPlane[1] * circle.fIsectPlane[1]) < 0.0f) {
1329 geoClipPlane.
set(circle.fClipPlane[1] - circle.fIsectPlane[1],
1330 circle.fIsectPlane[0] - circle.fClipPlane[0]);
1332 offsetClipDist = 0.5f / halfWidth;
1335 for (
int i = 0;
i < 8; ++
i) {
1345 vertices << circle.fClipPlane;
1347 if (fClipPlaneIsect) {
1348 vertices << circle.fIsectPlane;
1350 if (fClipPlaneUnion) {
1351 vertices << circle.fUnionPlane;
1354 vertices << circle.fRoundCapCenters;
1358 if (circle.fStroked) {
1361 for (
int i = 0;
i < 8; ++
i) {
1367 vertices << circle.fClipPlane;
1369 if (fClipPlaneIsect) {
1370 vertices << circle.fIsectPlane;
1372 if (fClipPlaneUnion) {
1373 vertices << circle.fUnionPlane;
1376 vertices << circle.fRoundCapCenters;
1383 vertices << circle.fClipPlane;
1385 if (fClipPlaneIsect) {
1386 vertices << circle.fIsectPlane;
1388 if (fClipPlaneUnion) {
1389 vertices << circle.fUnionPlane;
1392 vertices << circle.fRoundCapCenters;
1398 for (
int i = 0;
i < primIndexCount; ++
i) {
1399 *indices++ = primIndices[
i] + currStartVertex;
1405 fMesh =
target->allocMesh();
1406 fMesh->
setIndexed(std::move(indexBuffer), fIndexCount, firstIndex, 0, fVertCount - 1,
1411 if (!fProgramInfo || !fMesh) {
1424 if (fVertCount + that->fVertCount > 65536) {
1434 that->fViewMatrixIfUsingLocalCoords)) {
1440 fClipPlane |= that->fClipPlane;
1441 fClipPlaneIsect |= that->fClipPlaneIsect;
1442 fClipPlaneUnion |= that->fClipPlaneUnion;
1443 fRoundCaps |= that->fRoundCaps;
1444 fWideColor |= that->fWideColor;
1446 fCircles.push_back_n(that->fCircles.
size(), that->fCircles.
begin());
1447 fVertCount += that->fVertCount;
1448 fIndexCount += that->fIndexCount;
1449 fAllFill = fAllFill && that->fAllFill;
1453#if defined(GR_TEST_UTILS)
1454 SkString onDumpInfo()
const override {
1456 for (
int i = 0;
i < fCircles.size(); ++
i) {
1458 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f],"
1459 "InnerRad: %.2f, OuterRad: %.2f\n",
1460 fCircles[
i].fColor.toBytes_RGBA(), fCircles[
i].fDevBounds.fLeft,
1461 fCircles[
i].fDevBounds.fTop, fCircles[
i].fDevBounds.fRight,
1462 fCircles[
i].fDevBounds.fBottom, fCircles[
i].fInnerRadius,
1463 fCircles[
i].fOuterRadius);
1465 string += fHelper.dumpInfo();
1482 SkMatrix fViewMatrixIfUsingLocalCoords;
1489 bool fClipPlaneIsect;
1490 bool fClipPlaneUnion;
1517 SkASSERT(circle_stays_circle(viewMatrix));
1519 return Helper::FactoryHelper<ButtCapDashedCircleOp>(context, std::move(
paint), viewMatrix,
1521 onAngle, offAngle, phaseAngle);
1530 SkASSERT(circle_stays_circle(viewMatrix));
1550 auto totalAngle = onAngle + offAngle;
1551 phaseAngle =
SkScalarMod(phaseAngle + totalAngle / 2, totalAngle) - totalAngle / 2;
1560 SkScalar outerRadius = radius + halfWidth;
1561 SkScalar innerRadius = radius - halfWidth;
1569 fViewMatrixIfUsingLocalCoords = viewMatrix;
1576 totalAngle = -totalAngle;
1578 fCircles.push_back(Circle{
1590 radius += halfWidth;
1598 const char*
name()
const override {
return "ButtCappedDashedCircleOp"; }
1619 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
1621 void onCreateProgramInfo(
const GrCaps* caps,
1624 bool usesMSAASurface,
1632 if (!fViewMatrixIfUsingLocalCoords.
invert(&localMatrix)) {
1645 std::move(appliedClip),
1649 renderPassXferBarriers,
1654 if (!fProgramInfo) {
1656 if (!fProgramInfo) {
1664 fVertCount, &vertexBuffer, &firstVertex);
1666 SkDebugf(
"Could not allocate vertices\n");
1672 uint16_t* indices =
target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
1674 SkDebugf(
"Could not allocate indices\n");
1678 int currStartVertex = 0;
1679 for (
const auto& circle : fCircles) {
1683 auto normInnerRadius = circle.fInnerRadius / circle.fOuterRadius;
1685 bool reflect =
false;
1686 struct {
float onAngle, totalAngle,
startAngle, phaseAngle; } dashParams = {
1687 circle.fOnAngle, circle.fTotalAngle, circle.fStartAngle, circle.fPhaseAngle
1689 if (dashParams.totalAngle < 0) {
1691 dashParams.totalAngle = -dashParams.totalAngle;
1692 dashParams.startAngle = -dashParams.startAngle;
1704 auto reflectY = [=](
const SkPoint&
p) {
1705 return SkPoint{
p.fX, reflect ? -
p.fY :
p.fY };
1708 for (
int i = 0;
i < 8; ++
i) {
1712 << circle.fOuterRadius
1718 for (
int i = 0;
i < 8; ++
i) {
1722 << circle.fOuterRadius
1729 for (
int i = 0;
i < primIndexCount; ++
i) {
1730 *indices++ = primIndices[
i] + currStartVertex;
1736 fMesh =
target->allocMesh();
1737 fMesh->
setIndexed(std::move(indexBuffer), fIndexCount, firstIndex, 0, fVertCount - 1,
1742 if (!fProgramInfo || !fMesh) {
1755 if (fVertCount + that->fVertCount > 65536) {
1765 that->fViewMatrixIfUsingLocalCoords)) {
1769 fCircles.push_back_n(that->fCircles.
size(), that->fCircles.
begin());
1770 fVertCount += that->fVertCount;
1771 fIndexCount += that->fIndexCount;
1772 fWideColor |= that->fWideColor;
1776#if defined(GR_TEST_UTILS)
1777 SkString onDumpInfo()
const override {
1779 for (
int i = 0;
i < fCircles.size(); ++
i) {
1781 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f],"
1782 "InnerRad: %.2f, OuterRad: %.2f, OnAngle: %.2f, TotalAngle: %.2f, "
1784 fCircles[
i].fColor.toBytes_RGBA(), fCircles[
i].fDevBounds.fLeft,
1785 fCircles[
i].fDevBounds.fTop, fCircles[
i].fDevBounds.fRight,
1786 fCircles[
i].fDevBounds.fBottom, fCircles[
i].fInnerRadius,
1787 fCircles[
i].fOuterRadius, fCircles[
i].fOnAngle, fCircles[
i].fTotalAngle,
1788 fCircles[
i].fPhaseAngle);
1790 string += fHelper.dumpInfo();
1806 SkMatrix fViewMatrixIfUsingLocalCoords;
1825 struct DeviceSpaceParams {
1841 DeviceSpaceParams
params;
1865 params.fInnerXRadius = 0;
1866 params.fInnerYRadius = 0;
1883 (scaledStroke.
fY * scaledStroke.
fY) *
params.fXRadius ||
1885 (scaledStroke.
fX * scaledStroke.
fX) *
params.fYRadius) {
1895 params.fXRadius += scaledStroke.
fX;
1896 params.fYRadius += scaledStroke.
fY;
1903 const SkScalar kMaxOvalRadius = 16384;
1905 (
params.fXRadius >= kMaxOvalRadius ||
params.fYRadius >= kMaxOvalRadius)) {
1909 return Helper::FactoryHelper<EllipseOp>(context, std::move(
paint), viewMatrix,
1918 , fUseScale(
false) {
1932 fStroked = isStrokeOnly &&
params.fInnerXRadius > 0 &&
params.fInnerYRadius > 0;
1933 fViewMatrixIfUsingLocalCoords = viewMatrix;
1936 const char*
name()
const override {
return "EllipseOp"; }
1959 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
1961 void onCreateProgramInfo(
const GrCaps* caps,
1964 bool usesMSAASurface,
1970 if (!fViewMatrixIfUsingLocalCoords.
invert(&localMatrix)) {
1975 fUseScale, localMatrix);
1981 std::move(appliedClip),
1985 renderPassXferBarriers,
1990 if (!fProgramInfo) {
1992 if (!fProgramInfo) {
2000 SkDebugf(
"Could not allocate vertices\n");
2008 for (
const auto& ellipse : fEllipses) {
2010 SkScalar xRadius = ellipse.fXRadius;
2011 SkScalar yRadius = ellipse.fYRadius;
2014 struct {
float xOuter, yOuter, xInner, yInner; } invRadii = {
2020 SkScalar xMaxOffset = xRadius + aaBloat;
2021 SkScalar yMaxOffset = yRadius + aaBloat;
2026 xMaxOffset /= xRadius;
2027 yMaxOffset /= yRadius;
2031 verts.writeQuad(VertexWriter::TriStripFromRect(
2032 ellipse.fDevBounds.makeOutset(aaBloat, aaBloat)),
2034 origin_centered_tri_strip(xMaxOffset, yMaxOffset),
2035 VertexWriter::If(fUseScale,
std::max(xRadius, yRadius)),
2038 fMesh = helper.mesh();
2042 if (!fProgramInfo || !fMesh) {
2058 if (fStroked != that->fStroked) {
2064 that->fViewMatrixIfUsingLocalCoords)) {
2068 fEllipses.push_back_n(that->fEllipses.
size(), that->fEllipses.
begin());
2069 fWideColor |= that->fWideColor;
2073#if defined(GR_TEST_UTILS)
2074 SkString onDumpInfo()
const override {
2076 for (
const auto& geo : fEllipses) {
2078 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
2079 "XRad: %.2f, YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f\n",
2080 geo.fColor.toBytes_RGBA(), geo.fDevBounds.fLeft, geo.fDevBounds.fTop,
2081 geo.fDevBounds.fRight, geo.fDevBounds.fBottom, geo.fXRadius, geo.fYRadius,
2082 geo.fInnerXRadius, geo.fInnerYRadius);
2084 string += fHelper.dumpInfo();
2098 SkMatrix fViewMatrixIfUsingLocalCoords;
2117 struct DeviceSpaceParams {
2134 DeviceSpaceParams
params;
2146 params.fInnerXRadius = 0;
2147 params.fInnerYRadius = 0;
2188 const SkScalar kMaxOvalRadius = 16384;
2190 (
params.fXRadius >= kMaxOvalRadius ||
params.fYRadius >= kMaxOvalRadius)) {
2195 (
params.fInnerXRadius <= 0 ||
params.fInnerYRadius <= 0)) {
2198 return Helper::FactoryHelper<DIEllipseOp>(context, std::move(
paint),
params, viewMatrix);
2205 , fUseScale(
false) {
2214 fEllipses.emplace_back(
2225 const char*
name()
const override {
return "DIEllipseOp"; }
2248 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
2250 void onCreateProgramInfo(
const GrCaps* caps,
2253 bool usesMSAASurface,
2262 fProgramInfo = fHelper.
createProgramInfo(caps, arena, writeView, usesMSAASurface,
2263 std::move(appliedClip), dstProxyView, gp,
2265 renderPassXferBarriers, colorLoadOp);
2269 if (!fProgramInfo) {
2279 for (
const auto& ellipse : fEllipses) {
2281 SkScalar xRadius = ellipse.fXRadius;
2282 SkScalar yRadius = ellipse.fYRadius;
2288 ellipse.fGeoDy * aaBloat);
2292 float outerCoordX = drawBounds.
width() / (xRadius * 2);
2293 float outerCoordY = drawBounds.
height() / (yRadius * 2);
2296 float innerCoordX = 0;
2297 float innerCoordY = 0;
2302 innerCoordX = drawBounds.
width() / (ellipse.fInnerXRadius * 2);
2303 innerCoordY = drawBounds.
height() / (ellipse.fInnerYRadius * 2);
2306 verts.writeQuad(VertexWriter::TriStripFromRect(drawBounds),
2308 origin_centered_tri_strip(outerCoordX, outerCoordY),
2309 VertexWriter::If(fUseScale,
std::max(xRadius, yRadius)),
2310 origin_centered_tri_strip(innerCoordX, innerCoordY));
2312 fMesh = helper.mesh();
2316 if (!fProgramInfo || !fMesh) {
2331 if (this->style() != that->style()) {
2340 fEllipses.push_back_n(that->fEllipses.
size(), that->fEllipses.
begin());
2341 fWideColor |= that->fWideColor;
2345#if defined(GR_TEST_UTILS)
2346 SkString onDumpInfo()
const override {
2348 for (
const auto& geo : fEllipses) {
2350 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], XRad: %.2f, "
2351 "YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f, GeoDX: %.2f, "
2353 geo.fColor.toBytes_RGBA(), geo.fBounds.fLeft, geo.fBounds.fTop,
2354 geo.fBounds.fRight, geo.fBounds.fBottom, geo.fXRadius, geo.fYRadius,
2355 geo.fInnerXRadius, geo.fInnerYRadius, geo.fGeoDx, geo.fGeoDy);
2357 string += fHelper.dumpInfo();
2362 const SkMatrix& viewMatrix()
const {
return fEllipses[0].fViewMatrix; }
2426 16, 17, 19, 16, 19, 18,
2427 19, 17, 23, 19, 23, 21,
2428 21, 23, 22, 21, 22, 20,
2429 22, 16, 18, 22, 18, 20,
2434 8, 9, 13, 8, 13, 12,
2435 10, 11, 15, 10, 15, 14,
2440 6, 7, 11, 6, 11, 10,
2441 9, 10, 14, 9, 14, 13,
2526 float devStrokeWidth,
2528 return Helper::FactoryHelper<CircularRRectOp>(context, std::move(
paint), viewMatrix,
2530 devStrokeWidth, strokeOnly);
2533 const SkMatrix& viewMatrix,
const SkRect& devRect,
float devRadius,
2534 float devStrokeWidth,
bool strokeOnly)
2536 , fViewMatrixIfUsingLocalCoords(viewMatrix)
2539 SkASSERT(!(devStrokeWidth <= 0 && strokeOnly));
2544 if (devStrokeWidth > 0) {
2553 devStrokeWidth += 0.25f;
2556 if (devStrokeWidth <= devRect.
width() && devStrokeWidth <= devRect.
height()) {
2557 innerRadius = devRadius - halfWidth;
2561 outerRadius += halfWidth;
2584 const char*
name()
const override {
return "CircularRRectOp"; }
2614 << outerRadius << innerRadius;
2620 << outerRadius << innerRadius;
2625 << outerRadius << innerRadius;
2630 << outerRadius << innerRadius;
2635 << outerRadius << innerRadius;
2640 << outerRadius << innerRadius;
2646 << outerRadius << innerRadius;
2652 << outerRadius << innerRadius;
2655 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
2657 void onCreateProgramInfo(
const GrCaps* caps,
2660 bool usesMSAASurface,
2669 if (!fViewMatrixIfUsingLocalCoords.
invert(&localMatrix)) {
2674 false,
false,
false,
false,
2675 fWideColor, localMatrix);
2677 fProgramInfo = fHelper.
createProgramInfo(caps, arena, writeView, usesMSAASurface,
2678 std::move(appliedClip), dstProxyView, gp,
2680 renderPassXferBarriers, colorLoadOp);
2684 if (!fProgramInfo) {
2686 if (!fProgramInfo) {
2695 fVertCount, &vertexBuffer, &firstVertex);
2697 SkDebugf(
"Could not allocate vertices\n");
2703 uint16_t* indices =
target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
2705 SkDebugf(
"Could not allocate indices\n");
2709 int currStartVertex = 0;
2710 for (
const auto&
rrect : fRRects) {
2718 SkScalar yOuterRadii[4] = {-1, 0, 0, 1};
2723 : -1.0f /
rrect.fOuterRadius;
2724 for (
int i = 0;
i < 4; ++
i) {
2727 << -1.0f << yOuterRadii[
i]
2728 << outerRadius << innerRadius;
2732 << 0.0f << yOuterRadii[
i]
2733 << outerRadius << innerRadius;
2737 << 0.0f << yOuterRadii[
i]
2738 << outerRadius << innerRadius;
2742 << 1.0f << yOuterRadii[
i]
2743 << outerRadius << innerRadius;
2756 SkScalar overstrokeOuterRadius = outerRadius -
rrect.fInnerRadius;
2759 SkScalar maxOffset = -
rrect.fInnerRadius / overstrokeOuterRadius;
2761 FillInOverstrokeVerts(verts,
bounds, outerRadius, overstrokeOuterRadius, maxOffset,
2762 overstrokeOuterRadius, 0.0f,
color);
2767 for (
int i = 0;
i < primIndexCount; ++
i) {
2768 *indices++ = primIndices[
i] + currStartVertex;
2774 fMesh =
target->allocMesh();
2775 fMesh->
setIndexed(std::move(indexBuffer), fIndexCount, firstIndex, 0, fVertCount - 1,
2780 if (!fProgramInfo || !fMesh) {
2793 if (fVertCount + that->fVertCount > 65536) {
2803 that->fViewMatrixIfUsingLocalCoords)) {
2807 fRRects.push_back_n(that->fRRects.
size(), that->fRRects.
begin());
2808 fVertCount += that->fVertCount;
2809 fIndexCount += that->fIndexCount;
2810 fAllFill = fAllFill && that->fAllFill;
2811 fWideColor = fWideColor || that->fWideColor;
2815#if defined(GR_TEST_UTILS)
2816 SkString onDumpInfo()
const override {
2818 for (
int i = 0;
i < fRRects.size(); ++
i) {
2820 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f],"
2821 "InnerRad: %.2f, OuterRad: %.2f\n",
2822 fRRects[
i].fColor.toBytes_RGBA(), fRRects[
i].fDevBounds.fLeft,
2823 fRRects[
i].fDevBounds.fTop, fRRects[
i].fDevBounds.fRight,
2824 fRRects[
i].fDevBounds.fBottom, fRRects[
i].fInnerRadius,
2825 fRRects[
i].fOuterRadius);
2827 string += fHelper.dumpInfo();
2840 SkMatrix fViewMatrixIfUsingLocalCoords;
2894 SkASSERT(devXRadius >= 0.5 || strokeOnly);
2895 SkASSERT(devYRadius >= 0.5 || strokeOnly);
2896 SkASSERT((devStrokeWidths.
fX > 0) == (devStrokeWidths.
fY > 0));
2897 SkASSERT(!(strokeOnly && devStrokeWidths.
fX <= 0));
2898 if (devStrokeWidths.
fX > 0) {
2913 if (devStrokeWidths.
fX * (devYRadius * devYRadius) <
2914 (devStrokeWidths.
fY * devStrokeWidths.
fY) * devXRadius) {
2917 if (devStrokeWidths.
fY * (devXRadius * devXRadius) <
2918 (devStrokeWidths.
fX * devStrokeWidths.
fX) * devYRadius) {
2922 return Helper::FactoryHelper<EllipticalRRectOp>(context, std::move(
paint),
2923 viewMatrix, devRect,
2924 devXRadius, devYRadius, devStrokeWidths,
2929 const SkMatrix& viewMatrix,
const SkRect& devRect,
float devXRadius,
2930 float devYRadius,
SkVector devStrokeHalfWidths,
bool strokeOnly)
2933 , fUseScale(
false) {
2937 bool stroked =
false;
2938 if (devStrokeHalfWidths.
fX > 0) {
2941 innerXRadius = devXRadius - devStrokeHalfWidths.
fX;
2942 innerYRadius = devYRadius - devStrokeHalfWidths.
fY;
2943 stroked = (innerXRadius >= 0 && innerYRadius >= 0);
2946 devXRadius += devStrokeHalfWidths.
fX;
2947 devYRadius += devStrokeHalfWidths.
fY;
2952 fViewMatrixIfUsingLocalCoords = viewMatrix;
2954 fRRects.emplace_back(
2955 RRect{
color, devXRadius, devYRadius, innerXRadius, innerYRadius,
bounds});
2958 const char*
name()
const override {
return "EllipticalRRectOp"; }
2980 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
2982 void onCreateProgramInfo(
const GrCaps* caps,
2985 bool usesMSAASurface,
2991 if (!fViewMatrixIfUsingLocalCoords.
invert(&localMatrix)) {
2996 fUseScale, localMatrix);
2998 fProgramInfo = fHelper.
createProgramInfo(caps, arena, writeView, usesMSAASurface,
2999 std::move(appliedClip), dstProxyView, gp,
3001 renderPassXferBarriers, colorLoadOp);
3005 if (!fProgramInfo) {
3007 if (!fProgramInfo) {
3018 SkDebugf(
"Could not allocate indices\n");
3027 SkDebugf(
"Could not allocate vertices\n");
3031 for (
const auto&
rrect : fRRects) {
3034 float reciprocalRadii[4] = {
3044 reciprocalRadii[2] =
std::min(reciprocalRadii[2], 1e6f);
3045 reciprocalRadii[3] =
std::min(reciprocalRadii[3], 1e6f);
3055 SkScalar xMaxOffset = xOuterRadius;
3056 SkScalar yMaxOffset = yOuterRadius;
3060 xMaxOffset /=
rrect.fXRadius;
3061 yMaxOffset /=
rrect.fYRadius;
3068 SkScalar yOuterOffsets[4] = {yMaxOffset,
3073 auto maybeScale = VertexWriter::If(fUseScale,
std::max(
rrect.fXRadius,
rrect.fYRadius));
3074 for (
int i = 0;
i < 4; ++
i) {
3077 << xMaxOffset << yOuterOffsets[
i]
3095 << xMaxOffset << yOuterOffsets[
i]
3100 fMesh = helper.mesh();
3104 if (!fProgramInfo || !fMesh) {
3120 if (fStroked != that->fStroked) {
3126 that->fViewMatrixIfUsingLocalCoords)) {
3130 fRRects.push_back_n(that->fRRects.
size(), that->fRRects.
begin());
3131 fWideColor = fWideColor || that->fWideColor;
3135#if defined(GR_TEST_UTILS)
3136 SkString onDumpInfo()
const override {
3138 for (
const auto& geo : fRRects) {
3140 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
3141 "XRad: %.2f, YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f\n",
3142 geo.fColor.toBytes_RGBA(), geo.fDevBounds.fLeft, geo.fDevBounds.fTop,
3143 geo.fDevBounds.fRight, geo.fDevBounds.fBottom, geo.fXRadius, geo.fYRadius,
3144 geo.fInnerXRadius, geo.fInnerYRadius);
3146 string += fHelper.dumpInfo();
3160 SkMatrix fViewMatrixIfUsingLocalCoords;
3223 scaledStroke, isStrokeOnly);
3259 scaledStroke.
set(1, 1);
3291 xRadius, yRadius, scaledStroke, isStrokeOnly);
3322 circle_stays_circle(viewMatrix));
3324 auto r =
width / 2.f;
3335 if (offInterval == 0) {
3338 strokeStyle, shaderCaps);
3339 }
else if (onInterval == 0) {
3343 auto angularOnInterval = onInterval / r;
3344 auto angularOffInterval = offInterval / r;
3345 auto phaseAngle = style.
dashPhase() / r;
3348 static const SkScalar kStartAngle = 0.f;
3351 angularOnInterval, angularOffInterval, phaseAngle);
3414#if defined(GR_TEST_UTILS)
3417 if (numSamples > 1) {
3423 SkScalar translateX = random->nextSScalar1() * 1000.f;
3424 SkScalar translateY = random->nextSScalar1() * 1000.f;
3427 scale = random->nextSScalar1() * 100.f;
3428 }
while (
scale == 0);
3433 SkRect circle = GrTest::TestSquare(random);
3439 if (random->nextBool()) {
3442 arcParamsTmp.
fUseCenter = random->nextBool();
3443 arcParams = &arcParamsTmp;
3451 assert_alive(
paint);
3456 if (numSamples > 1) {
3461 SkScalar translateX = random->nextSScalar1() * 1000.f;
3462 SkScalar translateY = random->nextSScalar1() * 1000.f;
3465 scale = random->nextSScalar1() * 100.f;
3466 }
while (
scale == 0);
3471 SkRect circle = GrTest::TestSquare(random);
3475 SkScalar onAngle = random->nextRangeScalar(0.01f, 1000.f);
3476 SkScalar offAngle = random->nextRangeScalar(0.01f, 1000.f);
3478 SkScalar phase = random->nextRangeScalar(-1000.f, 1000.f);
3485 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
3486 SkRect ellipse = GrTest::TestSquare(random);
3488 GrTest::TestStrokeRec(random));
3492 SkMatrix viewMatrix = GrTest::TestMatrix(random);
3493 SkRect ellipse = GrTest::TestSquare(random);
3495 GrTest::TestStrokeRec(random));
3501 SkScalar translateX = random->nextSScalar1() * 1000.f;
3502 SkScalar translateY = random->nextSScalar1() * 1000.f;
3505 scale = random->nextSScalar1() * 100.f;
3506 }
while (
scale == 0);
3512 SkScalar radius = random->nextRangeF(0.1f, 10.f);
3519 GrTest::TestStrokeRec(random),
nullptr);
3523 assert_alive(
paint);
3527GR_DRAW_OP_TEST_DEFINE(RRectOp) {
3528 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
3529 const SkRRect&
rrect = GrTest::TestRRectSimple(random);
3531 GrTest::TestStrokeRec(random));
SkStrokeRec::Style fStyle
static const int strokeWidth
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
GrFragmentProcessor::ProgramImpl ProgramImpl
#define DEFINE_OP_CLASS_ID
static const uint16_t * circle_type_to_indices(bool stroked)
static constexpr SkPoint kOctagonOuter[]
static int rrect_type_to_vert_count(RRectType type)
static const int kVertsPerStandardRRect
static const uint16_t gOverstrokeRRectIndices[]
static int rrect_type_to_index_count(RRectType type)
static constexpr SkPoint kOctagonInner[]
static int circle_type_to_index_count(bool stroked)
static const int kVertsPerFillCircle
static const uint16_t gStrokeCircleIndices[]
GrOp::Owner make_rrect_op(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, const SkRRect &rrect, const SkStrokeRec &stroke)
static const uint16_t * gStandardRRectIndices
static const int kIndicesPerFillRRect
static const int kIndicesPerStrokeCircle
static const uint16_t gFillCircleIndices[]
static const int kIndicesPerOverstrokeRRect
static const int kIndicesPerFillCircle
SKGPU_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey)
static const int kVertsPerOverstrokeRRect
static const int kNumRRectsInIndexBuffer
static constexpr SkScalar kCosPi8
static const uint16_t * rrect_type_to_indices(RRectType type)
static sk_sp< const GrBuffer > get_rrect_index_buffer(RRectType type, GrResourceProvider *resourceProvider)
static constexpr SkScalar kOctOffset
static const int kIndicesPerStrokeRRect
static const int kVertsPerStrokeCircle
static constexpr SkScalar kSinPi8
static int circle_type_to_vert_count(bool stroked)
#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST
#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(...)
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
@ kFloat2_GrVertexAttribType
@ kFloat3_GrVertexAttribType
@ kFloat4_GrVertexAttribType
#define SKGPU_DEFINE_STATIC_UNIQUE_KEY(name)
#define SK_ABORT(message,...)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr float sk_ieee_float_divide(float numer, float denom)
static bool rotate(const SkDCubic &cubic, int zero, int index, SkDCubic &rotPath)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define INHERITED(method,...)
void swap(sk_sp< T > &a, sk_sp< T > &b)
#define SkDegreesToRadians(degrees)
#define SkScalarInvert(x)
#define SkScalarMod(x, y)
#define SkScalarATan2(y, x)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkScalarSin(radians)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
#define SK_ScalarNearlyZero
#define SkScalarCos(radians)
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static SkScalar center(float pos0, float pos1)
~ButtCapDashedCircleGeometryProcessor() override
const char * name() const override
void addToKey(const GrShaderCaps &caps, skgpu::KeyBuilder *b) const override
static GrGeometryProcessor * Make(SkArenaAlloc *arena, bool wideColor, const SkMatrix &localMatrix)
std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const override
static DEFINE_OP_CLASS_ID GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, SkPoint center, SkScalar radius, SkScalar strokeWidth, SkScalar startAngle, SkScalar onAngle, SkScalar offAngle, SkScalar phaseAngle)
const char * name() const override
GrProcessorSet::Analysis finalize(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
void visitProxies(const GrVisitProxyFunc &func) const override
ButtCapDashedCircleOp(GrProcessorSet *processorSet, const SkPMColor4f &color, const SkMatrix &viewMatrix, SkPoint center, SkScalar radius, SkScalar strokeWidth, SkScalar startAngle, SkScalar onAngle, SkScalar offAngle, SkScalar phaseAngle)
FixedFunctionFlags fixedFunctionFlags() const override
static GrGeometryProcessor * Make(SkArenaAlloc *arena, bool stroke, bool clipPlane, bool isectPlane, bool unionPlane, bool roundCaps, bool wideColor, const SkMatrix &localMatrix)
std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const override
const char * name() const override
void addToKey(const GrShaderCaps &caps, skgpu::KeyBuilder *b) const override
FixedFunctionFlags fixedFunctionFlags() const override
CircleOp(GrProcessorSet *processorSet, const SkPMColor4f &color, const SkMatrix &viewMatrix, SkPoint center, SkScalar radius, const GrStyle &style, const ArcParams *arcParams)
void visitProxies(const GrVisitProxyFunc &func) const override
const char * name() const override
GrProcessorSet::Analysis finalize(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
static GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, SkPoint center, SkScalar radius, const GrStyle &style, const ArcParams *arcParams=nullptr)
void visitProxies(const GrVisitProxyFunc &func) const override
GrProcessorSet::Analysis finalize(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
const char * name() const override
CircularRRectOp(GrProcessorSet *processorSet, const SkPMColor4f &color, const SkMatrix &viewMatrix, const SkRect &devRect, float devRadius, float devStrokeWidth, bool strokeOnly)
FixedFunctionFlags fixedFunctionFlags() const override
static DEFINE_OP_CLASS_ID GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, const SkRect &devRect, float devRadius, float devStrokeWidth, bool strokeOnly)
~DIEllipseGeometryProcessor() override
static GrGeometryProcessor * Make(SkArenaAlloc *arena, bool wideColor, bool useScale, const SkMatrix &viewMatrix, DIEllipseStyle style)
const char * name() const override
std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const override
void addToKey(const GrShaderCaps &caps, skgpu::KeyBuilder *b) const override
static DEFINE_OP_CLASS_ID GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, const SkRect &ellipse, const SkStrokeRec &stroke)
DIEllipseOp(GrProcessorSet *processorSet, const SkPMColor4f &color, const DeviceSpaceParams ¶ms, const SkMatrix &viewMatrix)
void visitProxies(const GrVisitProxyFunc &func) const override
GrProcessorSet::Analysis finalize(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
const char * name() const override
FixedFunctionFlags fixedFunctionFlags() const override
static GrGeometryProcessor * Make(SkArenaAlloc *arena, bool stroke, bool wideColor, bool useScale, const SkMatrix &localMatrix)
const char * name() const override
std::unique_ptr< ProgramImpl > makeProgramImpl(const GrShaderCaps &) const override
~EllipseGeometryProcessor() override
void addToKey(const GrShaderCaps &caps, skgpu::KeyBuilder *b) const override
void visitProxies(const GrVisitProxyFunc &func) const override
EllipseOp(GrProcessorSet *processorSet, const SkPMColor4f &color, const SkMatrix &viewMatrix, const DeviceSpaceParams ¶ms, const SkStrokeRec &stroke)
const char * name() const override
FixedFunctionFlags fixedFunctionFlags() const override
static DEFINE_OP_CLASS_ID GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, const SkRect &ellipse, const SkStrokeRec &stroke)
GrProcessorSet::Analysis finalize(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
const char * name() const override
GrProcessorSet::Analysis finalize(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType) override
EllipticalRRectOp(GrProcessorSet *processorSet, const SkPMColor4f &color, const SkMatrix &viewMatrix, const SkRect &devRect, float devXRadius, float devYRadius, SkVector devStrokeHalfWidths, bool strokeOnly)
void visitProxies(const GrVisitProxyFunc &func) const override
static DEFINE_OP_CLASS_ID GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, const SkRect &devRect, float devXRadius, float devYRadius, SkVector devStrokeWidths, bool strokeOnly)
FixedFunctionFlags fixedFunctionFlags() const override
const GrCaps * caps() const
const GrShaderCaps * shaderCaps() const
friend class GrSimpleMeshDrawOpHelper
void emitFunction(SkSLType returnType, const char *mangledName, SkSpan< const GrShaderVar > args, const char *body)
void codeAppend(const char *str)
SkString getMangledFunctionName(const char *baseName)
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
void emitAttributes(const GrGeometryProcessor &)
void addPassThroughAttribute(const GrShaderVar &vsVar, const char *output, Interpolation=Interpolation::kInterpolated)
void addVarying(const char *name, GrGLSLVarying *varying, Interpolation=Interpolation::kInterpolated)
GrShaderVar asShaderVar() const
constexpr bool isInitialized() const
constexpr const char * name() const
GrGLSLProgramDataManager::UniformHandle UniformHandle
static void WriteOutputPosition(GrGLSLVertexBuilder *, GrGPArgs *, const char *posName)
static void WriteLocalCoord(GrGLSLVertexBuilder *, GrGLSLUniformHandler *, const GrShaderCaps &, GrGPArgs *, GrShaderVar localVar, const SkMatrix &localMatrix, UniformHandle *localMatrixUniform)
static constexpr int kMatrixKeyBits
static uint32_t ComputeMatrixKey(const GrShaderCaps &caps, const SkMatrix &mat)
static void SetTransform(const GrGLSLProgramDataManager &, const GrShaderCaps &, const UniformHandle &uniform, const SkMatrix &matrix, SkMatrix *state=nullptr)
GrGeometryProcessor(ClassID)
size_t vertexStride() const
static Attribute MakeColorAttribute(const char *name, bool wideColor)
void setVertexAttributesWithImplicitOffsets(const Attribute *attrs, int attrCount)
void createProgramInfo(const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
GrMeshDrawOp(uint32_t classID)
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 SkRect & bounds() const
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
void setTransformedBounds(const SkRect &srcBounds, const SkMatrix &m, HasAABloat aabloat, IsHairline zeroArea)
static GrOp::Owner MakeArcOp(GrRecordingContext *, GrPaint &&, const SkMatrix &, const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const GrStyle &, const GrShaderCaps *)
static GrOp::Owner MakeOvalOp(GrRecordingContext *, GrPaint &&, const SkMatrix &, const SkRect &oval, const GrStyle &style, const GrShaderCaps *)
static GrOp::Owner MakeCircularRRectOp(GrRecordingContext *, GrPaint &&, const SkMatrix &, const SkRRect &, const SkStrokeRec &, const GrShaderCaps *)
static GrOp::Owner MakeCircleOp(GrRecordingContext *, GrPaint &&, const SkMatrix &, const SkRect &oval, const GrStyle &style, const GrShaderCaps *)
static GrOp::Owner MakeRRectOp(GrRecordingContext *, GrPaint &&, const SkMatrix &, const SkRRect &, const SkStrokeRec &, const GrShaderCaps *)
@ kCircleGeometryProcessor_ClassID
@ kEllipseGeometryProcessor_ClassID
@ kButtCapStrokedCircleGeometryProcessor_ClassID
@ kDIEllipseGeometryProcessor_ClassID
const GrPipeline & pipeline() const
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
GrRecordingContextPriv priv()
sk_sp< const GrGpuBuffer > findOrCreatePatternedIndexBuffer(const uint16_t *pattern, int patternSize, int reps, int vertCount, const skgpu::UniqueKey &key)
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)
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
bool isCompatible(const GrSimpleMeshDrawOpHelper &that, const GrCaps &, const SkRect &thisBounds, const SkRect &thatBounds, bool ignoreAAType=false) const
const SkScalar * dashIntervals() const
SkPathEffect * pathEffect() const
bool hasPathEffect() const
bool hasNonDashPathEffect() const
int dashIntervalCnt() const
SkScalar dashPhase() const
const SkStrokeRec & strokeRec() const
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
SkScalar mapRadius(SkScalar radius) const
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
static constexpr int kMScaleX
horizontal scale factor
SkScalar getSkewY() const
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
void mapVectors(SkVector dst[], const SkVector src[], int count) const
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
SkScalar getSkewX() const
bool invert(SkMatrix *inverse) const
bool rectStaysRect() const
SkMatrix & setRotate(SkScalar degrees, SkScalar px, SkScalar py)
SkScalar getScaleX() const
SkScalar getScaleY() const
static constexpr int kMSkewY
vertical skew factor
static constexpr int kMScaleY
vertical scale factor
bool isSimilarity(SkScalar tol=SK_ScalarNearlyZero) const
static constexpr int kMSkewX
horizontal skew factor
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
void mapVector(SkScalar dx, SkScalar dy, SkVector *result) const
static const SkMatrix & InvalidMatrix()
@ kButt_Cap
no stroke extension
static SkVector GetSimpleRadii(const SkRRect &rr)
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
const SkRect & getBounds() const
const char * c_str() const
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
SkScalar getWidth() const
SkPaint::Cap getCap() const
T & emplace_back(Args &&... args)
const EmbeddedViewParams * params
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float max(float r, float g, float b)
static float min(float r, float g, float b)
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
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
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
SkScalar fStartAngleRadians
SkScalar fSweepAngleRadians
bool fHasLowFragmentPrecision
void setIndexed(sk_sp< const GrBuffer > indexBuffer, int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue, GrPrimitiveRestart, sk_sp< const GrBuffer > vertexBuffer, int baseVertex)
float dot(const SkVector &vec) const
static constexpr SkPoint Make(float x, float y)
void set(float x, float y)
void scale(float scale, SkPoint *dst) const
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
void outset(float dx, float dy)
SkRect makeOutset(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 MakeLTRB(float l, float t, float r, float b)
SkScalar fTop
smaller y-axis bounds
bool fShaderDerivativeSupport