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 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); } } }