コード例 #1
0
void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) {
    // 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 = NULL;
    const SkMatrix* toSrc = NULL;
    if (hasPerspective) {
        geometryProcessorViewM = &this->viewMatrix();
        geometryProcessorLocalM = &SkMatrix::I();
        toDevice = &this->viewMatrix();
        toSrc = &invert;
    }

    // Setup geometry processors for worst case
    uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType |
                       GrDefaultGeoProcFactory::kCoverage_GPType;

    SkAutoTUnref<const GrGeometryProcessor> lineGP(
            GrDefaultGeoProcFactory::Create(gpFlags,
                                            this->color(),
                                            this->usesLocalCoords(),
                                            this->coverageIgnored(),
                                            *geometryProcessorViewM,
                                            *geometryProcessorLocalM,
                                            this->coverage()));

    SkAutoTUnref<const GrGeometryProcessor> quadGP(
            GrQuadEffect::Create(this->color(),
                                 *geometryProcessorViewM,
                                 kHairlineAA_GrProcessorEdgeType,
                                 batchTarget->caps(),
                                 *geometryProcessorLocalM,
                                 this->usesLocalCoords(),
                                 this->coverage()));

    SkAutoTUnref<const GrGeometryProcessor> conicGP(
            GrConicEffect::Create(this->color(),
                                  *geometryProcessorViewM,
                                  kHairlineAA_GrProcessorEdgeType,
                                  batchTarget->caps(),
                                  *geometryProcessorLocalM,
                                  this->usesLocalCoords(),
                                  this->coverage()));

    // 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 GrIndexBuffer> linesIndexBuffer(
            ref_lines_index_buffer(batchTarget->resourceProvider()));
        batchTarget->initDraw(lineGP, pipeline);

        const GrVertexBuffer* vertexBuffer;
        int firstVertex;

        size_t vertexStride = lineGP->getVertexStride();
        int vertexCount = kLineSegNumVertices * lineCount;
        LineVertex* verts = reinterpret_cast<LineVertex*>(
            batchTarget->makeVertSpace(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);
        }

        {
            GrVertices vertices;
            vertices.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, linesIndexBuffer,
                                   firstVertex, kLineSegNumVertices, kIdxsPerLineSeg, lineCount,
                                   kLineSegsNumInIdxBuffer);
            batchTarget->draw(vertices);
        }
    }

    if (quadCount || conicCount) {
        const GrVertexBuffer* vertexBuffer;
        int firstVertex;

        SkAutoTUnref<const GrIndexBuffer> quadsIndexBuffer(
            ref_quads_index_buffer(batchTarget->resourceProvider()));

        size_t vertexStride = sizeof(BezierVertex);
        int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * conicCount;
        void *vertices = batchTarget->makeVertSpace(vertexStride, vertexCount,
                                                    &vertexBuffer, &firstVertex);

        if (!vertices || !quadsIndexBuffer) {
            SkDebugf("Could not allocate vertices\n");
            return;
        }

        // Setup vertices
        BezierVertex* verts = 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, &verts);
        }

        // Start Conics
        for (int i = 0; i < conicCount; ++i) {
            add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts);
        }

        if (quadCount > 0) {
            batchTarget->initDraw(quadGP, pipeline);

            {
                GrVertices verts;
                verts.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
                                    firstVertex, kQuadNumVertices, kIdxsPerQuad, quadCount,
                                    kQuadsNumInIdxBuffer);
                batchTarget->draw(verts);
                firstVertex += quadCount * kQuadNumVertices;
           }
        }

        if (conicCount > 0) {
            batchTarget->initDraw(conicGP, pipeline);

            {
                GrVertices verts;
                verts.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
                                    firstVertex, kQuadNumVertices, kIdxsPerQuad, conicCount,
                                    kQuadsNumInIdxBuffer);
                batchTarget->draw(verts);
            }
        }
    }
}