58 static_assert(0 == kLine && 1 == kQuad);
65 const SkPoint& endNorm()
const {
73bool center_of_mass(
const SegmentArray& segments,
SkPoint* c) {
76 int count = segments.size();
85 p0 = segments[0].endPt();
91 pj = segments[1].endPt() - p0;
92 for (
int i = 1;
i <
count - 1; ++
i) {
94 pj = segments[
i + 1].endPt() - p0;
109 const SkPoint& pt = segments[
i].endPt();
126bool compute_vectors(SegmentArray* segments,
131 if (!center_of_mass(*segments, fanPt)) {
134 int count = segments->size();
144 int64_t vCount64 = 0;
145 int64_t iCount64 = 0;
148 Segment& sega = (*segments)[
a];
150 Segment& segb = (*segments)[
b];
152 const SkPoint* prevPt = &sega.endPt();
153 int n = segb.countPoints();
154 for (
int p = 0;
p < n; ++
p) {
155 segb.fNorms[
p] = segb.fPts[
p] - *prevPt;
158 prevPt = &segb.fPts[
p];
160 if (Segment::kLine == segb.fType) {
172 const Segment& sega = (*segments)[
a];
174 Segment& segb = (*segments)[
b];
175 segb.fMid = segb.fNorms[0] + sega.endNorm();
176 segb.fMid.normalize();
189struct DegenerateTestData {
190 DegenerateTestData() {
fStage = kInitial; }
191 bool isDegenerate()
const {
return kNonDegenerate !=
fStage; }
206void update_degenerate_test(DegenerateTestData*
data,
const SkPoint& pt) {
207 switch (
data->fStage) {
208 case DegenerateTestData::kInitial:
209 data->fFirstPoint = pt;
210 data->fStage = DegenerateTestData::kPoint;
212 case DegenerateTestData::kPoint:
214 data->fLineNormal = pt -
data->fFirstPoint;
215 data->fLineNormal.normalize();
217 data->fLineC = -
data->fLineNormal.dot(
data->fFirstPoint);
218 data->fStage = DegenerateTestData::kLine;
221 case DegenerateTestData::kLine:
223 data->fStage = DegenerateTestData::kNonDegenerate;
226 case DegenerateTestData::kNonDegenerate:
229 SK_ABORT(
"Unexpected degenerate test stage.");
254inline void add_line_to_segment(
const SkPoint& pt, SegmentArray* segments) {
255 segments->push_back();
256 segments->back().fType = Segment::kLine;
257 segments->back().fPts[0] = pt;
260inline void add_quad_segment(
const SkPoint pts[3], SegmentArray* segments) {
262 if (pts[0] != pts[2]) {
263 add_line_to_segment(pts[2], segments);
266 segments->push_back();
268 segments->back().fPts[0] = pts[1];
269 segments->back().fPts[1] = pts[2];
273inline void add_cubic_segments(
const SkPoint pts[4],
275 SegmentArray* segments) {
279 for (
int q = 0; q <
count; q += 3) {
280 add_quad_segment(&quads[q], segments);
286 SegmentArray* segments,
298 DegenerateTestData degenerateData;
300 if (!get_direction(
path,
m, &
dir)) {
310 update_degenerate_test(°enerateData, pts[0]);
314 m.mapPoints(&pts[1], 1);
315 update_degenerate_test(°enerateData, pts[1]);
316 add_line_to_segment(pts[1], segments);
323 update_degenerate_test(°enerateData, pts[1]);
324 update_degenerate_test(°enerateData, pts[2]);
325 add_quad_segment(pts, segments);
331 SkScalar weight = iter.conicWeight();
335 update_degenerate_test(°enerateData, quadPts[2*
i + 1]);
336 update_degenerate_test(°enerateData, quadPts[2*
i + 2]);
337 add_quad_segment(quadPts + 2*
i, segments);
345 update_degenerate_test(°enerateData, pts[1]);
346 update_degenerate_test(°enerateData, pts[2]);
347 update_degenerate_test(°enerateData, pts[3]);
348 add_cubic_segments(pts,
dir, segments);
353 if (degenerateData.isDegenerate()) {
356 return compute_vectors(segments, fanPt,
dir, vCount, iCount);
372void create_vertices(
const SegmentArray& segments,
374 const VertexColor&
color,
378 size_t vertexStride) {
381 int* v = &
draw->fVertexCnt;
382 int*
i = &
draw->fIndexCnt;
384 int count = segments.size();
386 const Segment& sega = segments[
a];
388 const Segment& segb = segments[
b];
393 if (Segment::kLine == segb.fType) {
398 if (
draw->fVertexCnt + vCount > (1 << 16)) {
400 draw = &draws->push_back();
401 v = &
draw->fVertexCnt;
402 i = &
draw->fIndexCnt;
415 idxs[*
i + 0] = *v + 0;
416 idxs[*
i + 1] = *v + 2;
417 idxs[*
i + 2] = *v + 1;
418 idxs[*
i + 3] = *v + 0;
419 idxs[*
i + 4] = *v + 3;
420 idxs[*
i + 5] = *v + 2;
425 if (Segment::kLine == segb.fType) {
432 verts << fanPt <<
color <<
SkPoint{0, dist} << negOneDists;
433 verts << v1Pos <<
color <<
SkPoint{0, 0} << negOneDists;
434 verts << v2Pos <<
color <<
SkPoint{0, 0} << negOneDists;
438 idxs[*
i + 0] = *v + 3;
439 idxs[*
i + 1] = *v + 1;
440 idxs[*
i + 2] = *v + 2;
442 idxs[*
i + 3] = *v + 4;
443 idxs[*
i + 4] = *v + 3;
444 idxs[*
i + 5] = *v + 2;
452 idxs[*
i + 0] = *v + 0;
453 idxs[*
i + 1] = *v + 2;
454 idxs[*
i + 2] = *v + 1;
461 SkPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
464 SkScalar c1 = segb.fNorms[1].dot(qpts[2]);
473 PosAndUV posAndUVPoints[6];
474 posAndUVPoints[0].fPos = fanPt;
475 posAndUVPoints[1].fPos = qpts[0];
476 posAndUVPoints[2].fPos = qpts[2];
477 posAndUVPoints[3].fPos = qpts[0] + segb.fNorms[0];
478 posAndUVPoints[4].fPos = qpts[2] + segb.fNorms[1];
479 SkVector midVec = segb.fNorms[0] + segb.fNorms[1];
481 posAndUVPoints[5].fPos = qpts[1] + midVec;
484 toUV.
apply(posAndUVPoints, 6,
sizeof(PosAndUV),
sizeof(
SkPoint));
486 verts << posAndUVPoints[0].fPos <<
color << posAndUVPoints[0].fUV
487 << (-segb.fNorms[0].dot(fanPt) + c0)
488 << (-segb.fNorms[1].dot(fanPt) + c1);
490 verts << posAndUVPoints[1].fPos <<
color << posAndUVPoints[1].fUV
492 << (-segb.fNorms[1].dot(qpts[0]) + c1);
494 verts << posAndUVPoints[2].fPos <<
color << posAndUVPoints[2].fUV
495 << (-segb.fNorms[0].dot(qpts[2]) + c0)
501 verts << posAndUVPoints[3].fPos <<
color << posAndUVPoints[3].fUV
502 << kStableLargeNegativeValue
503 << kStableLargeNegativeValue;
505 verts << posAndUVPoints[4].fPos <<
color << posAndUVPoints[4].fUV
506 << kStableLargeNegativeValue
507 << kStableLargeNegativeValue;
509 verts << posAndUVPoints[5].fPos <<
color << posAndUVPoints[5].fUV
510 << kStableLargeNegativeValue
511 << kStableLargeNegativeValue;
513 idxs[*
i + 0] = *v + 3;
514 idxs[*
i + 1] = *v + 1;
515 idxs[*
i + 2] = *v + 2;
516 idxs[*
i + 3] = *v + 4;
517 idxs[*
i + 4] = *v + 3;
518 idxs[*
i + 5] = *v + 2;
520 idxs[*
i + 6] = *v + 5;
521 idxs[*
i + 7] = *v + 3;
522 idxs[*
i + 8] = *v + 4;
530 idxs[*
i + 0] = *v + 0;
531 idxs[*
i + 1] = *v + 2;
532 idxs[*
i + 2] = *v + 1;
558 bool usesLocalCoords,
560 return arena->
make([&](
void* ptr) {
561 return new (ptr) QuadEdgeEffect(localMatrix, usesLocalCoords, wideColor);
565 ~QuadEdgeEffect()
override {}
567 const char*
name()
const override {
return "QuadEdge"; }
569 void addToKey(
const GrShaderCaps& caps, KeyBuilder*
b)
const override {
570 b->addBool(fUsesLocalCoords,
"usesLocalCoords");
571 b->addBits(ProgramImpl::kMatrixKeyBits,
572 ProgramImpl::ComputeMatrixKey(caps, fLocalMatrix),
576 std::unique_ptr<ProgramImpl> makeProgramImpl(
const GrShaderCaps&)
const override;
579 QuadEdgeEffect(
const SkMatrix& localMatrix,
bool usesLocalCoords,
bool wideColor)
581 , fLocalMatrix(localMatrix)
582 , fUsesLocalCoords(usesLocalCoords) {
584 fInColor = MakeColorAttribute(
"inColor", wideColor);
587 this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
595 bool fUsesLocalCoords;
602std::unique_ptr<GrGeometryProcessor::ProgramImpl> QuadEdgeEffect::makeProgramImpl(
609 const QuadEdgeEffect& qe = geomProc.
cast<QuadEdgeEffect>();
610 SetTransform(pdman, shaderCaps, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix);
614 void onEmitCode(EmitArgs&
args, GrGPArgs* gpArgs)
override {
615 const QuadEdgeEffect& qe =
args.fGeomProc.cast<QuadEdgeEffect>();
628 vertBuilder->codeAppendf(
"%s = %s;", v.vsOut(), qe.fInQuadEdge.name());
635 WriteOutputPosition(vertBuilder, gpArgs, qe.fInPosition.name());
636 if (qe.fUsesLocalCoords) {
637 WriteLocalCoord(vertBuilder,
641 qe.fInPosition.asShaderVar(),
643 &fLocalMatrixUniform);
649 fragBuilder->
codeAppendf(
"half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
650 fragBuilder->
codeAppendf(
"half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
651 fragBuilder->
codeAppendf(
"if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn());
653 fragBuilder->
codeAppendf(
"edgeAlpha = half(min(min(%s.z, %s.w) + 0.5, 1.0));", v.fsIn(),
656 fragBuilder->
codeAppendf(
"half2 gF = half2(half(2.0*%s.x*duvdx.x - duvdx.y),"
657 " half(2.0*%s.x*duvdy.x - duvdy.y));",
659 fragBuilder->
codeAppendf(
"edgeAlpha = half(%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(),
662 "saturate(0.5 - edgeAlpha / length(gF));}");
664 fragBuilder->
codeAppendf(
"half4 %s = half4(edgeAlpha);",
args.fOutputCoverage);
670 UniformHandle fLocalMatrixUniform;
673 return std::make_unique<Impl>();
678#if defined(GR_TEST_UTILS)
680 SkMatrix localMatrix = GrTest::TestMatrix(
d->fRandom);
681 bool usesLocalCoords =
d->fRandom->nextBool();
682 bool wideColor =
d->fRandom->nextBool();
684 return d->caps()->shaderCaps()->fShaderDerivativeSupport
702 return Helper::FactoryHelper<AAConvexPathOp>(context, std::move(
paint), viewMatrix,
path,
710 fPaths.emplace_back(PathData{viewMatrix,
path,
color});
711 this->setTransformedBounds(
path.getBounds(), viewMatrix, HasAABloat::kYes,
715 const char*
name()
const override {
return "AAConvexPathOp"; }
725 FixedFunctionFlags fixedFunctionFlags()
const override {
return fHelper.
fixedFunctionFlags(); }
731 &fPaths.back().fColor, &fWideColor);
735 GrProgramInfo* programInfo()
override {
return fProgramInfo; }
737 void onCreateProgramInfo(
const GrCaps* caps,
740 bool usesMSAASurface,
755 std::move(appliedClip),
756 dstProxyView, quadProcessor,
758 renderPassXferBarriers, colorLoadOp);
762 int instanceCount = fPaths.size();
765 this->createProgramInfo(
target);
773 fDraws.reserve(instanceCount);
776 for (
int i = 0;
i < instanceCount;
i++) {
777 const PathData&
args = fPaths[
i];
792 pathPtr = tmpPathPtr;
798 kPreallocSegmentCnt = 512 /
sizeof(Segment),
799 kPreallocDrawCnt = 4,
804 if (!get_segments(*pathPtr, *viewMatrix, &segments, &fanPt, &vertexCount,
812 VertexWriter verts =
target->makeVertexWriter(kVertexStride,
818 SkDebugf(
"Could not allocate vertices\n");
825 uint16_t *idxs =
target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
827 SkDebugf(
"Could not allocate indices\n");
832 VertexColor
color(
args.fColor, fWideColor);
833 create_vertices(segments, fanPt,
color, &draws, verts, idxs, kVertexStride);
836 for (
int j = 0; j < draws.
size(); ++j) {
841 firstIndex +=
draw.fIndexCnt;
842 firstVertex +=
draw.fVertexCnt;
845 fDraws.push_back({ meshes, draws.
size() });
850 if (!fProgramInfo || fDraws.empty()) {
856 for (
int i = 0;
i < fDraws.size(); ++
i) {
857 for (
int j = 0; j < fDraws[
i].fMeshCount; ++j) {
864 AAConvexPathOp* that = t->
cast<AAConvexPathOp>();
865 if (!fHelper.
isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
866 return CombineResult::kCannotCombine;
870 return CombineResult::kCannotCombine;
873 fPaths.push_back_n(that->fPaths.size(), that->fPaths.begin());
874 fWideColor |= that->fWideColor;
875 return CombineResult::kMerged;
878#if defined(GR_TEST_UTILS)
879 SkString onDumpInfo()
const override {
880 return SkStringPrintf(
"Count: %d\n%s", fPaths.size(), fHelper.dumpInfo().c_str());
912 if (
args.fCaps->shaderCaps()->fShaderDerivativeSupport &&
914 !
args.fShape->inverseFilled() &&
args.fShape->knownToBeConvex() &&
915 args.fShape->knownDirection()) {
921bool AAConvexPathRenderer::onDrawPath(
const DrawPathArgs&
args) {
923 "AAConvexPathRenderer::onDrawPath");
933 args.fSurfaceDrawContext->addDrawOp(
args.fClip, std::move(op));
939#if defined(GR_TEST_UTILS)
941GR_DRAW_OP_TEST_DEFINE(AAConvexPathOp) {
942 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
943 const SkPath&
path = GrTest::TestPathConvex(random);
946 context, std::move(
paint), viewMatrix,
path, stencilSettings);
enum skgpu::ganesh::@8120::DegenerateTestData::@384 fStage
enum skgpu::ganesh::@8120::Segment::@383 fType
static constexpr SkScalar kCloseSqd
#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename)
#define DEFINE_OP_CLASS_ID
#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST
#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(...)
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
@ kFloat2_GrVertexAttribType
@ kFloat4_GrVertexAttribType
#define SK_ABORT(message,...)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr bool SkIsNaN(T x)
static constexpr int32_t SK_MaxS32
@ kClose
SkPath::RawIter returns 0 points.
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define INHERITED(method,...)
#define SkScalarInvert(x)
static bool SkScalarNearlyZero(SkScalar x, 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.
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
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)
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
void apply(void *vertices, int vertexCount, size_t stride, size_t uvOffset) const
const GrPipeline & pipeline() const
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
GrProcessorSet::Analysis finalizeProcessors(const GrCaps &caps, const GrAppliedClip *clip, GrClampType clampType, GrProcessorAnalysisCoverage geometryCoverage, GrProcessorAnalysisColor *geometryColor)
void visitProxies(const GrVisitProxyFunc &func) const
GrDrawOp::FixedFunctionFlags fixedFunctionFlags() const
bool isCompatible(const GrSimpleMeshDrawOpHelperWithStencil &that, const GrCaps &, const SkRect &thisBounds, const SkRect &thatBounds, bool ignoreAAType=false) const
bool usesLocalCoords() const
GrProgramInfo * createProgramInfoWithStencil(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
static constexpr int kMScaleX
horizontal scale factor
static const SkMatrix & I()
bool hasPerspective() const
static constexpr int kMSkewY
vertical skew factor
static constexpr int kMScaleY
vertical scale factor
static constexpr int kMSkewX
horizontal skew factor
static const SkMatrix & InvalidMatrix()
static SkPathFirstDirection ComputeFirstDirection(const SkPath &)
static bool AllPointsEq(const SkPoint pts[], int count)
static SkPathFirstDirection OppositeFirstDirection(SkPathFirstDirection dir)
SkPath & setIsVolatile(bool isVolatile)
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
static SkPoint MakeOrthog(const SkPoint &vec, Side side=kLeft_Side)
static SkScalar DistanceToLineBetween(const SkPoint &pt, const SkPoint &a, const SkPoint &b, Side *side=nullptr)
static SkScalar DistanceToLineSegmentBetweenSqd(const SkPoint &pt, const SkPoint &a, const SkPoint &b)
static SkScalar DistanceToSqd(const SkPoint &pt, const SkPoint &a)
T * init(Args &&... args)
static void Draw(SkCanvas *canvas, const SkRect &rect)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
void convertCubicToQuadsConstrainToTangents(const SkPoint p[4], SkScalar tolScale, SkPathFirstDirection dir, skia_private::TArray< SkPoint, true > *quads)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
@ kPoint
Draws a point at each input vertex.
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)
static float CrossProduct(const SkVector &a, const SkVector &b)
float dot(const SkVector &vec) const
void set(float x, float y)
void scale(float scale, SkPoint *dst) const
std::shared_ptr< const fml::Mapping > data