diff options
author | senorblanco <senorblanco@chromium.org> | 2016-03-10 08:38:45 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-10 08:38:45 -0800 |
commit | 6599efffeef3168dfc68dca99c30454c5c23b859 (patch) | |
tree | a605fb7f6ecb9a8c13da21e416ee339685012a5f /src | |
parent | e7bbe0378233d16aa0921965f4a4ccc66b2eeec3 (diff) |
GrTessellator: abstract vertex allocation into caller.
This abstracts all vertex allocation out of GrTessellator via a VertexBuffer interface. This removes all GPU-related calls from GrTessellator.
It also factors vertex drawing into GrTessellatingPathRenderer::drawVertices(), and makes tessellate() (now draw() also responsible for drawing. This means the cache hit case is clearer as an early-out,
and storing into cache is done in draw() as well.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1776003002
Review URL: https://codereview.chromium.org/1776003002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrTessellator.cpp | 37 | ||||
-rw-r--r-- | src/gpu/GrTessellator.h | 17 | ||||
-rw-r--r-- | src/gpu/batches/GrTessellatingPathRenderer.cpp | 129 |
3 files changed, 103 insertions, 80 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp index a8fa79e560..f4195dfb03 100644 --- a/src/gpu/GrTessellator.cpp +++ b/src/gpu/GrTessellator.cpp @@ -7,17 +7,11 @@ #include "GrTessellator.h" -#include "GrBatchFlushState.h" -#include "GrBatchTest.h" -#include "GrDefaultGeoProcFactory.h" #include "GrPathUtils.h" -#include "GrVertices.h" -#include "GrResourceCache.h" -#include "GrResourceProvider.h" -#include "SkGeometry.h" -#include "SkChunkAlloc.h" -#include "batches/GrVertexBatch.h" +#include "SkChunkAlloc.h" +#include "SkGeometry.h" +#include "SkPath.h" #include <stdio.h> @@ -1370,8 +1364,7 @@ namespace GrTessellator { // Stage 6: Triangulate the monotone polygons into a vertex buffer. int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds, - GrResourceProvider* resourceProvider, - SkAutoTUnref<GrVertexBuffer>& vertexBuffer, bool canMapVB, bool* isLinear) { + VertexAllocator* vertexAllocator, bool* isLinear) { int contourCnt; int sizeEstimate; get_contour_count_and_size_estimate(path, tolerance, &contourCnt, &sizeEstimate); @@ -1387,21 +1380,11 @@ int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBo return 0; } - size_t size = count * sizeof(SkPoint); - if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) { - vertexBuffer.reset(resourceProvider->createVertexBuffer( - size, GrResourceProvider::kStatic_BufferUsage, 0)); - } - if (!vertexBuffer.get()) { + SkPoint* verts = vertexAllocator->lock(count); + if (!verts) { SkDebugf("Could not allocate vertices\n"); return 0; } - SkPoint* verts; - if (canMapVB) { - verts = static_cast<SkPoint*>(vertexBuffer->map()); - } else { - verts = new SkPoint[count]; - } SkPoint* end = verts; for (Poly* poly = polys; poly; poly = poly->fNext) { if (apply_fill_type(fillType, poly->fWinding)) { @@ -1411,13 +1394,7 @@ int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBo int actualCount = static_cast<int>(end - verts); LOG("actual count: %d\n", actualCount); SkASSERT(actualCount <= count); - if (canMapVB) { - vertexBuffer->unmap(); - } else { - vertexBuffer->updateData(verts, actualCount * sizeof(SkPoint)); - delete[] verts; - } - + vertexAllocator->unlock(actualCount); return actualCount; } diff --git a/src/gpu/GrTessellator.h b/src/gpu/GrTessellator.h index 4304920fbc..9e7d5f0b13 100644 --- a/src/gpu/GrTessellator.h +++ b/src/gpu/GrTessellator.h @@ -8,8 +8,10 @@ #ifndef GrTessellator_DEFINED #define GrTessellator_DEFINED -#include "SkPath.h" -#include "GrResourceProvider.h" +#include "SkPoint.h" + +class SkPath; +struct SkRect; /** * Provides utility functions for converting paths to a collection of triangles. @@ -19,6 +21,13 @@ namespace GrTessellator { +class VertexAllocator { +public: + virtual ~VertexAllocator() {} + virtual SkPoint* lock(int vertexCount) = 0; + virtual void unlock(int actualCount) = 0; +}; + struct WindingVertex { SkPoint fPos; int fWinding; @@ -32,9 +41,7 @@ int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBou WindingVertex** verts); int PathToTriangles(const SkPath& path, SkScalar tolerance, const SkRect& clipBounds, - GrResourceProvider* resourceProvider, - SkAutoTUnref<GrVertexBuffer>& vertexBuffer, bool canMapVB, bool* isLinear); - + VertexAllocator*, bool *isLinear); } #endif diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp index a312db654c..85c2ca0738 100644 --- a/src/gpu/batches/GrTessellatingPathRenderer.cpp +++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp @@ -59,6 +59,48 @@ bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { return false; } +class StaticVertexAllocator : public GrTessellator::VertexAllocator { +public: + StaticVertexAllocator(SkAutoTUnref<GrVertexBuffer>& vertexBuffer, + GrResourceProvider* resourceProvider, + bool canMapVB) + : fVertexBuffer(vertexBuffer) + , fResourceProvider(resourceProvider) + , fCanMapVB(canMapVB) + , fVertices(nullptr) { + } + SkPoint* lock(int vertexCount) override { + size_t size = vertexCount * sizeof(SkPoint); + if (!fVertexBuffer.get() || fVertexBuffer->gpuMemorySize() < size) { + fVertexBuffer.reset(fResourceProvider->createVertexBuffer( + size, GrResourceProvider::kStatic_BufferUsage, 0)); + } + if (!fVertexBuffer.get()) { + return nullptr; + } + if (fCanMapVB) { + fVertices = static_cast<SkPoint*>(fVertexBuffer->map()); + } else { + fVertices = new SkPoint[vertexCount]; + } + return fVertices; + } + void unlock(int actualCount) override { + if (fCanMapVB) { + fVertexBuffer->unmap(); + } else { + fVertexBuffer->updateData(fVertices, actualCount * sizeof(SkPoint)); + delete[] fVertices; + } + fVertices = nullptr; + } +private: + SkAutoTUnref<GrVertexBuffer>& fVertexBuffer; + GrResourceProvider* fResourceProvider; + bool fCanMapVB; + SkPoint* fVertices; +}; + } // namespace GrTessellatingPathRenderer::GrTessellatingPathRenderer() { @@ -103,46 +145,7 @@ private: fPipelineInfo = overrides; } - int tessellate(GrUniqueKey* key, - GrResourceProvider* resourceProvider, - SkAutoTUnref<GrVertexBuffer>& vertexBuffer, - bool canMapVB) const { - SkPath path; - GrStrokeInfo stroke(fStroke); - if (stroke.isDashed()) { - if (!stroke.applyDashToPath(&path, &stroke, fPath)) { - return 0; - } - } else { - path = fPath; - } - if (!stroke.isFillStyle()) { - stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); - if (!stroke.applyToPath(&path, path)) { - return 0; - } - stroke.setFillStyle(); - } - SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; - SkRect pathBounds = path.getBounds(); - SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, pathBounds); - - bool isLinear; - int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, resourceProvider, - vertexBuffer, canMapVB, &isLinear); - if (!fPath.isVolatile()) { - TessInfo info; - info.fTolerance = isLinear ? 0 : tol; - info.fCount = count; - SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); - key->setCustomData(data.get()); - resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()); - SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key)); - } - return count; - } - - void onPrepareDraws(Target* target) const override { + void draw(Target* target, const GrGeometryProcessor* gp) const { // construct a cache key from the path's genID and the view matrix static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; @@ -164,15 +167,47 @@ private: SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; SkScalar tol = GrPathUtils::scaleToleranceToSrc( screenSpaceTol, fViewMatrix, fPath.getBounds()); - if (!cache_match(vertexBuffer.get(), tol, &actualCount)) { - bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); - actualCount = this->tessellate(&key, rp, vertexBuffer, canMapVB); + if (cache_match(vertexBuffer.get(), tol, &actualCount)) { + this->drawVertices(target, gp, vertexBuffer.get(), 0, actualCount); + return; } - if (actualCount == 0) { + SkPath path; + GrStrokeInfo stroke(fStroke); + if (stroke.isDashed()) { + if (!stroke.applyDashToPath(&path, &stroke, fPath)) { + return; + } + } else { + path = fPath; + } + if (!stroke.isFillStyle()) { + stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); + if (!stroke.applyToPath(&path, path)) { + return; + } + stroke.setFillStyle(); + } + bool isLinear; + bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); + StaticVertexAllocator allocator(vertexBuffer, target->resourceProvider(), canMapVB); + int count = GrTessellator::PathToTriangles(path, tol, fClipBounds, &allocator, &isLinear); + if (count == 0) { return; } + this->drawVertices(target, gp, vertexBuffer.get(), 0, count); + if (!fPath.isVolatile()) { + TessInfo info; + info.fTolerance = isLinear ? 0 : tol; + info.fCount = count; + SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); + key.setCustomData(data.get()); + target->resourceProvider()->assignUniqueKeyToResource(key, vertexBuffer.get()); + SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(key)); + } + } + void onPrepareDraws(Target* target) const override { SkAutoTUnref<const GrGeometryProcessor> gp; { using namespace GrDefaultGeoProcFactory; @@ -191,14 +226,18 @@ private: gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoords, fViewMatrix)); } + this->draw(target, gp.get()); + } + void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrVertexBuffer* vb, + int firstVertex, int count) const { target->initDraw(gp, this->pipeline()); SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); GrPrimitiveType primitiveType = TESSELLATOR_WIREFRAME ? kLines_GrPrimitiveType : kTriangles_GrPrimitiveType; GrVertices vertices; - vertices.init(primitiveType, vertexBuffer.get(), 0, actualCount); + vertices.init(primitiveType, vb, firstVertex, count); target->draw(vertices); } |