コード例 #1
0
    void draw(GrBatchTarget* batchTarget, const GrPipeline* pipeline, int vertexCount, 
            size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) {
        if (vertexCount == 0 || indexCount == 0) {
            return;
        }
        const GrVertexBuffer* vertexBuffer;
        GrVertices info;
        int firstVertex;
        void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount, &vertexBuffer, 
                &firstVertex);
        if (!verts) {
            SkDebugf("Could not allocate vertices\n");
            return;
        }
        memcpy(verts, vertices, vertexCount * vertexStride);

        const GrIndexBuffer* indexBuffer;
        int firstIndex;
        uint16_t* idxs = batchTarget->makeIndexSpace(indexCount, &indexBuffer, &firstIndex);
        if (!idxs) {
            SkDebugf("Could not allocate indices\n");
            return;
        }
        memcpy(idxs, indices, indexCount * sizeof(uint16_t));
        info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, 
                firstIndex, vertexCount, indexCount);
        batchTarget->draw(info);
    }
コード例 #2
0
    void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
        SkAutoTUnref<const GrGeometryProcessor> gp(
                GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType,
                                                this->color(),
                                                this->viewMatrix(),
                                                SkMatrix::I(),
                                                this->coverage()));

        size_t vertexStride = gp->getVertexStride();
        SkASSERT(vertexStride == sizeof(SkPoint));

        batchTarget->initDraw(gp, pipeline);

        // TODO this is hacky, but the only way we have to initialize the GP is to use the
        // GrPipelineInfo struct so we can generate the correct shader.  Once we have GrBatch
        // everywhere we can remove this nastiness
        GrPipelineInfo init;
        init.fColorIgnored = fBatch.fColorIgnored;
        init.fOverrideColor = GrColor_ILLEGAL;
        init.fCoverageIgnored = fBatch.fCoverageIgnored;
        init.fUsesLocalCoords = this->usesLocalCoords();
        gp->initBatchTracker(batchTarget->currentBatchTracker(), init);

        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++) {
            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 GrVertexBuffer* vertexBuffer;
        int firstVertex;

        void* verts = batchTarget->makeVertSpace(vertexStride, maxVertices,
                                                 &vertexBuffer, &firstVertex);

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

        const GrIndexBuffer* indexBuffer = NULL;
        int firstIndex = 0;

        void* indices = NULL;
        if (isIndexed) {
            indices = batchTarget->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++) {
            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);
        }

        GrVertices vertices;
        if (isIndexed) {
            vertices.initIndexed(primitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex,
                                 vertexOffset, indexOffset);
        } else {
            vertices.init(primitiveType, vertexBuffer, firstVertex, vertexOffset);
        }
        batchTarget->draw(vertices);

        // put back reserves
        batchTarget->putBackIndices((size_t)(maxIndices - indexOffset));
        batchTarget->putBackVertices((size_t)(maxVertices - vertexOffset), (size_t)vertexStride);
    }
コード例 #3
0
    void prepareLinesOnlyDraws(Target* target) {
        bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();

        // Setup GrGeometryProcessor
        SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_gp(canTweakAlphaForCoverage,
                                                                  this->viewMatrix(),
                                                                  this->usesLocalCoords(),
                                                                  this->coverageIgnored()));
        if (!gp) {
            SkDebugf("Could not create GrGeometryProcessor\n");
            return;
        }

        target->initDraw(gp, this->pipeline());

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

            Geometry& args = fGeoData[i];

            if (!tess.tessellate(args.fViewMatrix, args.fPath)) {
                continue;
            }

            const GrVertexBuffer* vertexBuffer;
            int firstVertex;

            void* verts = target->makeVertexSpace(vertexStride, tess.numPts(), &vertexBuffer,
                                                  &firstVertex);
            if (!verts) {
                SkDebugf("Could not allocate vertices\n");
                return;
            }

            const GrIndexBuffer* 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);

            GrVertices info;
            info.initIndexed(kTriangles_GrPrimitiveType,
                             vertexBuffer, indexBuffer,
                             firstVertex, firstIndex,
                             tess.numPts(), tess.numIndices());
            target->draw(info);
        }
    }
コード例 #4
0
    void onPrepareDraws(Target* target) 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
        SkAutoTUnref<GrGeometryProcessor> quadProcessor(
                QuadEdgeEffect::Create(this->color(), invert, this->usesLocalCoords()));

        target->initDraw(quadProcessor, this->pipeline());

        // TODO generate all segments for all paths and use one vertex buffer
        for (int i = 0; i < instanceCount; i++) {
            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;
            if (viewMatrix->hasPerspective()) {
                args.fPath.transform(*viewMatrix);
                viewMatrix = &SkMatrix::I();
            }

            int vertexCount;
            int indexCount;
            enum {
                kPreallocSegmentCnt = 512 / sizeof(Segment),
                kPreallocDrawCnt = 4,
            };
            SkSTArray<kPreallocSegmentCnt, Segment, true> segments;
            SkPoint fanPt;

            if (!get_segments(args.fPath, *viewMatrix, &segments, &fanPt, &vertexCount,
                              &indexCount)) {
                continue;
            }

            const GrVertexBuffer* 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 GrIndexBuffer* 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);

            GrVertices vertices;

            for (int j = 0; j < draws.count(); ++j) {
                const Draw& draw = draws[j];
                vertices.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
                                     firstVertex, firstIndex, draw.fVertexCnt, draw.fIndexCnt);
                target->draw(vertices);
                firstVertex += draw.fVertexCnt;
                firstIndex += draw.fIndexCnt;
            }
        }
    }
コード例 #5
0
    void onPrepareDraws(Target* target) override {
        SkAutoTUnref<const 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.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoords,
                                                     this->viewMatrix()));
        }

        size_t vertexStride = gp->getVertexStride();
        SkASSERT(vertexStride == sizeof(SkPoint));

        target->initDraw(gp, this->pipeline());

        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++) {
            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 GrVertexBuffer* vertexBuffer;
        int firstVertex;

        void* verts = target->makeVertexSpace(vertexStride, maxVertices,
                                              &vertexBuffer, &firstVertex);

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

        const GrIndexBuffer* 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++) {
            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);
        }

        GrVertices vertices;
        if (isIndexed) {
            vertices.initIndexed(primitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex,
                                 vertexOffset, indexOffset);
        } else {
            vertices.init(primitiveType, vertexBuffer, firstVertex, vertexOffset);
        }
        target->draw(vertices);

        // put back reserves
        target->putBackIndices((size_t)(maxIndices - indexOffset));
        target->putBackVertices((size_t)(maxVertices - vertexOffset), (size_t)vertexStride);
    }