aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar senorblanco <senorblanco@chromium.org>2016-03-10 08:38:45 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-10 08:38:45 -0800
commit6599efffeef3168dfc68dca99c30454c5c23b859 (patch)
treea605fb7f6ecb9a8c13da21e416ee339685012a5f /src
parente7bbe0378233d16aa0921965f4a4ccc66b2eeec3 (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.cpp37
-rw-r--r--src/gpu/GrTessellator.h17
-rw-r--r--src/gpu/batches/GrTessellatingPathRenderer.cpp129
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);
}