void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuffer* vb, int firstVertex, int count) const { SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? kLines_GrPrimitiveType : kTriangles_GrPrimitiveType; GrMesh mesh; mesh.init(primitiveType, vb, firstVertex, count); target->draw(gp, mesh); }
void onPrepareDraws(Target* target) const override { sk_sp<GrGeometryProcessor> gp; { using namespace GrDefaultGeoProcFactory; Color color(this->color()); Coverage coverage(this->coverageIgnored() ? Coverage::kSolid_Type : Coverage::kNone_Type); LocalCoords localCoords(this->usesLocalCoords() ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type); gp = GrDefaultGeoProcFactory::Make(color, coverage, localCoords, this->viewMatrix()); } size_t vertexStride = gp->getVertexStride(); SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr)); const Geometry& args = fGeoData[0]; int vertexCount = kVertsPerHairlineRect; if (args.fStrokeWidth > 0) { vertexCount = kVertsPerStrokeRect; } const GrBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; } SkPoint* vertex = reinterpret_cast<SkPoint*>(verts); GrPrimitiveType primType; if (args.fStrokeWidth > 0) { primType = kTriangleStrip_GrPrimitiveType; init_stroke_rect_strip(vertex, args.fRect, args.fStrokeWidth); } else { // hairline primType = kLineStrip_GrPrimitiveType; vertex[0].set(args.fRect.fLeft, args.fRect.fTop); vertex[1].set(args.fRect.fRight, args.fRect.fTop); vertex[2].set(args.fRect.fRight, args.fRect.fBottom); vertex[3].set(args.fRect.fLeft, args.fRect.fBottom); vertex[4].set(args.fRect.fLeft, args.fRect.fTop); } GrMesh mesh; mesh.init(primType, vertexBuffer, firstVertex, vertexCount); target->draw(gp.get(), mesh); }
void onPrepareDraws(Target* target) const override { sk_sp<GrGeometryProcessor> gp; { using namespace GrDefaultGeoProcFactory; Color color(this->color()); Coverage coverage(this->coverage()); if (this->coverageIgnored()) { coverage.fType = Coverage::kNone_Type; } LocalCoords localCoords(this->usesLocalCoords() ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type); gp = GrDefaultGeoProcFactory::Make(color, coverage, localCoords, this->viewMatrix()); } size_t vertexStride = gp->getVertexStride(); SkASSERT(vertexStride == sizeof(SkPoint)); int instanceCount = fGeoData.count(); // compute number of vertices int maxVertices = 0; // We will use index buffers if we have multiple paths or one path with multiple contours bool isIndexed = instanceCount > 1; for (int i = 0; i < instanceCount; i++) { const Geometry& args = fGeoData[i]; int contourCount; maxVertices += GrPathUtils::worstCasePointCount(args.fPath, &contourCount, args.fTolerance); isIndexed = isIndexed || contourCount > 1; } if (maxVertices == 0 || maxVertices > ((int)SK_MaxU16 + 1)) { //SkDebugf("Cannot render path (%d)\n", maxVertices); return; } // determine primitiveType int maxIndices = 0; GrPrimitiveType primitiveType; if (this->isHairline()) { if (isIndexed) { maxIndices = 2 * maxVertices; primitiveType = kLines_GrPrimitiveType; } else { primitiveType = kLineStrip_GrPrimitiveType; } } else { if (isIndexed) { maxIndices = 3 * maxVertices; primitiveType = kTriangles_GrPrimitiveType; } else { primitiveType = kTriangleFan_GrPrimitiveType; } } // allocate vertex / index buffers const GrBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, maxVertices, &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; } const GrBuffer* indexBuffer = nullptr; int firstIndex = 0; void* indices = nullptr; if (isIndexed) { indices = target->makeIndexSpace(maxIndices, &indexBuffer, &firstIndex); if (!indices) { SkDebugf("Could not allocate indices\n"); return; } } // fill buffers int vertexOffset = 0; int indexOffset = 0; for (int i = 0; i < instanceCount; i++) { const Geometry& args = fGeoData[i]; int vertexCnt = 0; int indexCnt = 0; if (!this->createGeom(verts, vertexOffset, indices, indexOffset, &vertexCnt, &indexCnt, args.fPath, args.fTolerance, isIndexed)) { return; } vertexOffset += vertexCnt; indexOffset += indexCnt; SkASSERT(vertexOffset <= maxVertices && indexOffset <= maxIndices); } GrMesh mesh; if (isIndexed) { mesh.initIndexed(primitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex, vertexOffset, indexOffset); } else { mesh.init(primitiveType, vertexBuffer, firstVertex, vertexOffset); } target->draw(gp.get(), mesh); // put back reserves target->putBackIndices((size_t)(maxIndices - indexOffset)); target->putBackVertices((size_t)(maxVertices - vertexOffset), (size_t)vertexStride); }
void onPrepareDraws(Target* target) const override { SkMatrix invert; if (fUsesLocalCoords && !fViewMatrix.invert(&invert)) { SkDebugf("Could not invert viewmatrix\n"); return; } // Setup GrGeometryProcessors SkAutoTUnref<GrPLSGeometryProcessor> triangleProcessor( PLSAATriangleEffect::Create(invert, fUsesLocalCoords)); SkAutoTUnref<GrPLSGeometryProcessor> quadProcessor( PLSQuadEdgeEffect::Create(invert, fUsesLocalCoords)); GrResourceProvider* rp = target->resourceProvider(); SkRect bounds; this->bounds().roundOut(&bounds); triangleProcessor->setBounds(bounds); quadProcessor->setBounds(bounds); // We use the fact that SkPath::transform path does subdivision based on // perspective. Otherwise, we apply the view matrix when copying to the // segment representation. const SkMatrix* viewMatrix = &fViewMatrix; // We avoid initializing the path unless we have to const SkPath* pathPtr = &fPath; SkTLazy<SkPath> tmpPath; if (viewMatrix->hasPerspective()) { SkPath* tmpPathPtr = tmpPath.init(*pathPtr); tmpPathPtr->setIsVolatile(true); tmpPathPtr->transform(*viewMatrix); viewMatrix = &SkMatrix::I(); pathPtr = tmpPathPtr; } GrMesh mesh; PLSVertices triVertices; PLSVertices quadVertices; if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp, bounds)) { return; } if (triVertices.count()) { const GrBuffer* triVertexBuffer; int firstTriVertex; size_t triStride = triangleProcessor->getVertexStride(); PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace( triStride, triVertices.count(), &triVertexBuffer, &firstTriVertex)); if (!triVerts) { SkDebugf("Could not allocate vertices\n"); return; } for (int i = 0; i < triVertices.count(); ++i) { triVerts[i] = triVertices[i]; } mesh.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriVertex, triVertices.count()); target->draw(triangleProcessor, mesh); } if (quadVertices.count()) { const GrBuffer* quadVertexBuffer; int firstQuadVertex; size_t quadStride = quadProcessor->getVertexStride(); PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace( quadStride, quadVertices.count(), &quadVertexBuffer, &firstQuadVertex)); if (!quadVerts) { SkDebugf("Could not allocate vertices\n"); return; } for (int i = 0; i < quadVertices.count(); ++i) { quadVerts[i] = quadVertices[i]; } mesh.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex, quadVertices.count()); target->draw(quadProcessor, mesh); } SkAutoTUnref<GrGeometryProcessor> finishProcessor( PLSFinishEffect::Create(fColor, pathPtr->getFillType() == SkPath::FillType::kEvenOdd_FillType, invert, fUsesLocalCoords)); const GrBuffer* rectVertexBuffer; size_t finishStride = finishProcessor->getVertexStride(); int firstRectVertex; static const int kRectVertexCount = 6; SkPoint* rectVerts = reinterpret_cast<SkPoint*>(target->makeVertexSpace( finishStride, kRectVertexCount, &rectVertexBuffer, &firstRectVertex)); if (!rectVerts) { SkDebugf("Could not allocate vertices\n"); return; } rectVerts[0] = { bounds.fLeft, bounds.fTop }; rectVerts[1] = { bounds.fLeft, bounds.fBottom }; rectVerts[2] = { bounds.fRight, bounds.fBottom }; rectVerts[3] = { bounds.fLeft, bounds.fTop }; rectVerts[4] = { bounds.fRight, bounds.fTop }; rectVerts[5] = { bounds.fRight, bounds.fBottom }; mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVertex, kRectVertexCount); target->draw(finishProcessor, mesh); }