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);
    }
示例#3
0
    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);
    }
示例#4
0
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);
}
示例#6
0
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;
}
示例#7
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);
    }
示例#8
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);
        }
    }
}
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);
        }
    }
}
示例#10
0
    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);
    }
示例#11
0
    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;
            }
        }
    }
示例#12
0
    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);
        }
    }