void draw(GrVertexBatch::Target* target, const GrGeometryProcessor* gp, int vertexCount, size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const { if (vertexCount == 0 || indexCount == 0) { return; } const GrBuffer* vertexBuffer; GrMesh mesh; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; } memcpy(verts, vertices, vertexCount * vertexStride); const GrBuffer* indexBuffer; int firstIndex; uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); if (!idxs) { SkDebugf("Could not allocate indices\n"); return; } memcpy(idxs, indices, indexCount * sizeof(uint16_t)); mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex, vertexCount, indexCount); target->draw(gp, mesh); }
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 GrAtlasTextBatch::flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const { GrMesh mesh; int maxGlyphsPerDraw = static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6); mesh.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer, flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->fGlyphsToFlush, maxGlyphsPerDraw); target->draw(flushInfo->fGeometryProcessor.get(), mesh); flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush; flushInfo->fGlyphsToFlush = 0; }
void GrDrawVerticesOp::drawVertices(Target* target, sk_sp<const GrGeometryProcessor> gp, const GrBuffer* vertexBuffer, int firstVertex, const GrBuffer* indexBuffer, int firstIndex) { GrMesh* mesh = target->allocMesh(this->primitiveType()); if (this->isIndexed()) { mesh->setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1, GrPrimitiveRestart::kNo); } else { mesh->setNonIndexedNonInstanced(fVertexCount); } mesh->setVertexData(vertexBuffer, firstVertex); auto pipe = fHelper.makePipeline(target); target->draw(std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState, mesh); }
void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const { if (!flushInfo->fGlyphsToFlush) { return; } auto atlasManager = target->atlasManager(); GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get(); GrMaskFormat maskFormat = this->maskFormat(); unsigned int numActiveProxies; const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(maskFormat, &numActiveProxies); SkASSERT(proxies); if (gp->numTextureSamplers() != (int) numActiveProxies) { // During preparation the number of atlas pages has increased. // Update the proxies used in the GP to match. for (unsigned i = gp->numTextureSamplers(); i < numActiveProxies; ++i) { flushInfo->fFixedDynamicState->fPrimitiveProcessorTextures[i] = proxies[i].get(); } if (this->usesDistanceFields()) { if (this->isLCD()) { reinterpret_cast<GrDistanceFieldLCDTextGeoProc*>(gp)->addNewProxies( proxies, numActiveProxies, GrSamplerState::ClampBilerp()); } else { reinterpret_cast<GrDistanceFieldA8TextGeoProc*>(gp)->addNewProxies( proxies, numActiveProxies, GrSamplerState::ClampBilerp()); } } else { GrSamplerState samplerState = fNeedsGlyphTransform ? GrSamplerState::ClampBilerp() : GrSamplerState::ClampNearest(); reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(proxies, numActiveProxies, samplerState); } } int maxGlyphsPerDraw = static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6); GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles); mesh->setIndexedPatterned(flushInfo->fIndexBuffer.get(), kIndicesPerGlyph, kVerticesPerGlyph, flushInfo->fGlyphsToFlush, maxGlyphsPerDraw); mesh->setVertexData(flushInfo->fVertexBuffer.get(), flushInfo->fVertexOffset); target->draw(flushInfo->fGeometryProcessor, flushInfo->fPipeline, flushInfo->fFixedDynamicState, mesh); flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush; flushInfo->fGlyphsToFlush = 0; }
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 AAHairlineOp::onPrepareDraws(Target* target) { // Setup the viewmatrix and localmatrix for the GrGeometryProcessor. SkMatrix invert; if (!this->viewMatrix().invert(&invert)) { return; } // we will transform to identity space if the viewmatrix does not have perspective bool hasPerspective = this->viewMatrix().hasPerspective(); const SkMatrix* geometryProcessorViewM = &SkMatrix::I(); const SkMatrix* geometryProcessorLocalM = &invert; const SkMatrix* toDevice = nullptr; const SkMatrix* toSrc = nullptr; if (hasPerspective) { geometryProcessorViewM = &this->viewMatrix(); geometryProcessorLocalM = &SkMatrix::I(); toDevice = &this->viewMatrix(); toSrc = &invert; } // This is hand inlined for maximum performance. PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; PREALLOC_PTARRAY(128) conics; IntArray qSubdivs; FloatArray cWeights; int quadCount = 0; int instanceCount = fPaths.count(); bool convertConicsToQuads = !target->caps().shaderCaps()->floatIs32Bits(); for (int i = 0; i < instanceCount; i++) { const PathData& args = fPaths[i]; quadCount += gather_lines_and_quads(args.fPath, args.fViewMatrix, args.fDevClipBounds, args.fCapLength, convertConicsToQuads, &lines, &quads, &conics, &qSubdivs, &cWeights); } int lineCount = lines.count() / 2; int conicCount = conics.count() / 3; int quadAndConicCount = conicCount + quadCount; static constexpr int kMaxLines = SK_MaxS32 / kLineSegNumVertices; static constexpr int kMaxQuadsAndConics = SK_MaxS32 / kQuadNumVertices; if (lineCount > kMaxLines || quadAndConicCount > kMaxQuadsAndConics) { return; } // do lines first if (lineCount) { sk_sp<GrGeometryProcessor> lineGP; { using namespace GrDefaultGeoProcFactory; Color color(this->color()); LocalCoords localCoords(fHelper.usesLocalCoords() ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type); localCoords.fMatrix = geometryProcessorLocalM; lineGP = GrDefaultGeoProcFactory::Make(target->caps().shaderCaps(), color, Coverage::kAttribute_Type, localCoords, *geometryProcessorViewM); } sk_sp<const GrBuffer> linesIndexBuffer = get_lines_index_buffer(target->resourceProvider()); sk_sp<const GrBuffer> vertexBuffer; int firstVertex; SkASSERT(sizeof(LineVertex) == lineGP->vertexStride()); int vertexCount = kLineSegNumVertices * lineCount; LineVertex* verts = reinterpret_cast<LineVertex*>(target->makeVertexSpace( sizeof(LineVertex), vertexCount, &vertexBuffer, &firstVertex)); if (!verts|| !linesIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } for (int i = 0; i < lineCount; ++i) { add_line(&lines[2*i], toSrc, this->coverage(), &verts); } GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles); mesh->setIndexedPatterned(std::move(linesIndexBuffer), kIdxsPerLineSeg, kLineSegNumVertices, lineCount, kLineSegsNumInIdxBuffer); mesh->setVertexData(std::move(vertexBuffer), firstVertex); target->recordDraw(std::move(lineGP), mesh); } if (quadCount || conicCount) { sk_sp<GrGeometryProcessor> quadGP(GrQuadEffect::Make(this->color(), *geometryProcessorViewM, GrClipEdgeType::kHairlineAA, target->caps(), *geometryProcessorLocalM, fHelper.usesLocalCoords(), this->coverage())); sk_sp<GrGeometryProcessor> conicGP(GrConicEffect::Make(this->color(), *geometryProcessorViewM, GrClipEdgeType::kHairlineAA, target->caps(), *geometryProcessorLocalM, fHelper.usesLocalCoords(), this->coverage())); sk_sp<const GrBuffer> vertexBuffer; int firstVertex; sk_sp<const GrBuffer> quadsIndexBuffer = get_quads_index_buffer(target->resourceProvider()); SkASSERT(sizeof(BezierVertex) == quadGP->vertexStride()); SkASSERT(sizeof(BezierVertex) == conicGP->vertexStride()); int vertexCount = kQuadNumVertices * quadAndConicCount; void* vertices = target->makeVertexSpace(sizeof(BezierVertex), vertexCount, &vertexBuffer, &firstVertex); if (!vertices || !quadsIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } // Setup vertices BezierVertex* bezVerts = reinterpret_cast<BezierVertex*>(vertices); int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { SkASSERT(qSubdivs[i] >= 0); add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &bezVerts); } // Start Conics for (int i = 0; i < conicCount; ++i) { add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &bezVerts); } if (quadCount > 0) { GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles); mesh->setIndexedPatterned(quadsIndexBuffer, kIdxsPerQuad, kQuadNumVertices, quadCount, kQuadsNumInIdxBuffer); mesh->setVertexData(vertexBuffer, firstVertex); target->recordDraw(std::move(quadGP), mesh); firstVertex += quadCount * kQuadNumVertices; } if (conicCount > 0) { GrMesh* mesh = target->allocMesh(GrPrimitiveType::kTriangles); mesh->setIndexedPatterned(std::move(quadsIndexBuffer), kIdxsPerQuad, kQuadNumVertices, conicCount, kQuadsNumInIdxBuffer); mesh->setVertexData(std::move(vertexBuffer), firstVertex); target->recordDraw(std::move(conicGP), mesh); } } }
void AAHairlineBatch::onPrepareDraws(Target* target) const { // Setup the viewmatrix and localmatrix for the GrGeometryProcessor. SkMatrix invert; if (!this->viewMatrix().invert(&invert)) { return; } // we will transform to identity space if the viewmatrix does not have perspective bool hasPerspective = this->viewMatrix().hasPerspective(); const SkMatrix* geometryProcessorViewM = &SkMatrix::I(); const SkMatrix* geometryProcessorLocalM = &invert; const SkMatrix* toDevice = nullptr; const SkMatrix* toSrc = nullptr; if (hasPerspective) { geometryProcessorViewM = &this->viewMatrix(); geometryProcessorLocalM = &SkMatrix::I(); toDevice = &this->viewMatrix(); toSrc = &invert; } // This is hand inlined for maximum performance. PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; PREALLOC_PTARRAY(128) conics; IntArray qSubdivs; FloatArray cWeights; int quadCount = 0; int instanceCount = fGeoData.count(); for (int i = 0; i < instanceCount; i++) { const Geometry& args = fGeoData[i]; quadCount += gather_lines_and_quads(args.fPath, args.fViewMatrix, args.fDevClipBounds, &lines, &quads, &conics, &qSubdivs, &cWeights); } int lineCount = lines.count() / 2; int conicCount = conics.count() / 3; // do lines first if (lineCount) { SkAutoTUnref<const GrGeometryProcessor> lineGP; { using namespace GrDefaultGeoProcFactory; Color color(this->color()); Coverage coverage(Coverage::kAttribute_Type); LocalCoords localCoords(this->usesLocalCoords() ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type); localCoords.fMatrix = geometryProcessorLocalM; lineGP.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoords, *geometryProcessorViewM)); } SkAutoTUnref<const GrBuffer> linesIndexBuffer( ref_lines_index_buffer(target->resourceProvider())); const GrBuffer* vertexBuffer; int firstVertex; size_t vertexStride = lineGP->getVertexStride(); int vertexCount = kLineSegNumVertices * lineCount; LineVertex* verts = reinterpret_cast<LineVertex*>( target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex)); if (!verts|| !linesIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex)); for (int i = 0; i < lineCount; ++i) { add_line(&lines[2*i], toSrc, this->coverage(), &verts); } GrMesh mesh; mesh.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, linesIndexBuffer, firstVertex, kLineSegNumVertices, kIdxsPerLineSeg, lineCount, kLineSegsNumInIdxBuffer); target->draw(lineGP, mesh); } if (quadCount || conicCount) { SkAutoTUnref<const GrGeometryProcessor> quadGP( GrQuadEffect::Create(this->color(), *geometryProcessorViewM, kHairlineAA_GrProcessorEdgeType, target->caps(), *geometryProcessorLocalM, this->usesLocalCoords(), this->coverage())); SkAutoTUnref<const GrGeometryProcessor> conicGP( GrConicEffect::Create(this->color(), *geometryProcessorViewM, kHairlineAA_GrProcessorEdgeType, target->caps(), *geometryProcessorLocalM, this->usesLocalCoords(), this->coverage())); const GrBuffer* vertexBuffer; int firstVertex; SkAutoTUnref<const GrBuffer> quadsIndexBuffer( ref_quads_index_buffer(target->resourceProvider())); size_t vertexStride = sizeof(BezierVertex); int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * conicCount; void *vertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex); if (!vertices || !quadsIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } // Setup vertices BezierVertex* bezVerts = reinterpret_cast<BezierVertex*>(vertices); int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { SkASSERT(qSubdivs[i] >= 0); add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &bezVerts); } // Start Conics for (int i = 0; i < conicCount; ++i) { add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &bezVerts); } if (quadCount > 0) { GrMesh mesh; mesh.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer, firstVertex, kQuadNumVertices, kIdxsPerQuad, quadCount, kQuadsNumInIdxBuffer); target->draw(quadGP, mesh); firstVertex += quadCount * kQuadNumVertices; } if (conicCount > 0) { GrMesh mesh; mesh.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer, firstVertex, kQuadNumVertices, kIdxsPerQuad, conicCount, kQuadsNumInIdxBuffer); target->draw(conicGP, mesh); } } }
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); }
void onPrepareDraws(Target* target) const override { #ifndef SK_IGNORE_LINEONLY_AA_CONVEX_PATH_OPTS if (this->linesOnly()) { this->prepareLinesOnlyDraws(target); return; } #endif int instanceCount = fGeoData.count(); SkMatrix invert; if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) { SkDebugf("Could not invert viewmatrix\n"); return; } // Setup GrGeometryProcessor sk_sp<GrGeometryProcessor> quadProcessor( QuadEdgeEffect::Make(this->color(), invert, this->usesLocalCoords())); // TODO generate all segments for all paths and use one vertex buffer for (int i = 0; i < instanceCount; i++) { const Geometry& args = fGeoData[i]; // 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 = &args.fViewMatrix; // We avoid initializing the path unless we have to const SkPath* pathPtr = &args.fPath; SkTLazy<SkPath> tmpPath; if (viewMatrix->hasPerspective()) { SkPath* tmpPathPtr = tmpPath.init(*pathPtr); tmpPathPtr->setIsVolatile(true); tmpPathPtr->transform(*viewMatrix); viewMatrix = &SkMatrix::I(); pathPtr = tmpPathPtr; } int vertexCount; int indexCount; enum { kPreallocSegmentCnt = 512 / sizeof(Segment), kPreallocDrawCnt = 4, }; SkSTArray<kPreallocSegmentCnt, Segment, true> segments; SkPoint fanPt; if (!get_segments(*pathPtr, *viewMatrix, &segments, &fanPt, &vertexCount, &indexCount)) { continue; } const GrBuffer* vertexBuffer; int firstVertex; size_t vertexStride = quadProcessor->getVertexStride(); QuadVertex* verts = reinterpret_cast<QuadVertex*>(target->makeVertexSpace( vertexStride, vertexCount, &vertexBuffer, &firstVertex)); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; } const GrBuffer* indexBuffer; int firstIndex; uint16_t *idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); if (!idxs) { SkDebugf("Could not allocate indices\n"); return; } SkSTArray<kPreallocDrawCnt, Draw, true> draws; create_vertices(segments, fanPt, &draws, verts, idxs); GrMesh mesh; for (int j = 0; j < draws.count(); ++j) { const Draw& draw = draws[j]; mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex, draw.fVertexCnt, draw.fIndexCnt); target->draw(quadProcessor.get(), mesh); firstVertex += draw.fVertexCnt; firstIndex += draw.fIndexCnt; } } }
void prepareLinesOnlyDraws(Target* target) const { bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); // Setup GrGeometryProcessor sk_sp<GrGeometryProcessor> gp(create_fill_gp(canTweakAlphaForCoverage, this->viewMatrix(), this->usesLocalCoords(), this->coverageIgnored())); if (!gp) { SkDebugf("Could not create GrGeometryProcessor\n"); return; } size_t vertexStride = gp->getVertexStride(); SkASSERT(canTweakAlphaForCoverage ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) : vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); GrAAConvexTessellator tess; int instanceCount = fGeoData.count(); for (int i = 0; i < instanceCount; i++) { tess.rewind(); const Geometry& args = fGeoData[i]; if (!tess.tessellate(args.fViewMatrix, args.fPath)) { continue; } const GrBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, tess.numPts(), &vertexBuffer, &firstVertex); if (!verts) { SkDebugf("Could not allocate vertices\n"); return; } const GrBuffer* indexBuffer; int firstIndex; uint16_t* idxs = target->makeIndexSpace(tess.numIndices(), &indexBuffer, &firstIndex); if (!idxs) { SkDebugf("Could not allocate indices\n"); return; } extract_verts(tess, verts, vertexStride, args.fColor, idxs, canTweakAlphaForCoverage); GrMesh mesh; mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex, tess.numPts(), tess.numIndices()); target->draw(gp.get(), mesh); } }