Index: src/gpu/GrAAConcavePathRenderer.cpp |
diff --git a/src/gpu/GrAAConcavePathRenderer.cpp b/src/gpu/GrAAConcavePathRenderer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b7a0a20ae962ce042eeb3d02a86f95fd325ee1c5 |
--- /dev/null |
+++ b/src/gpu/GrAAConcavePathRenderer.cpp |
@@ -0,0 +1,145 @@ |
+/* |
+ * Copyright 2014 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "GrAAConcavePathRenderer.h" |
+ |
+#include "GrDefaultGeoProcFactory.h" |
+#include "GrPathUtils.h" |
+#include "SkString.h" |
+#include "SkStrokeRec.h" |
+#include "SkTLazy.h" |
+#include "SkTraceEvent.h" |
+#include "SkScan.h" |
+ |
+#include "batches/GrVertexBatch.h" |
+#include "GrBatchFlushState.h" |
+ |
+#include <stdio.h> // FIXME |
+ |
+class AAConcavePathBatch : public GrVertexBatch { |
+public: |
+ struct Geometry { |
+ GrColor fColor; |
+ SkMatrix fViewMatrix; |
+ SkPath fPath; |
+ SkIRect fClipBounds; |
+ bool fAntiAlias; |
+ }; |
+ |
+ static GrDrawBatch* Create(const Geometry& geometry) { |
+ return SkNEW_ARGS(AAConcavePathBatch, (geometry)); |
+ } |
+ |
+ const char* name() const override { return "AAConcavePathBatch"; } |
+ |
+ void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
+ out->setKnownFourComponents(fGeometry.fColor); |
+ } |
+ void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
+ out->setUnknownSingleComponent(); |
+ } |
+ |
+private: |
+ void initBatchTracker(const GrPipelineOptimizations& opt) override { |
+ // Handle any color overrides |
+ if (!opt.readsColor()) { |
+ fGeometry.fColor = GrColor_ILLEGAL; |
+ } |
+ opt.getOverrideColorIfSet(&fGeometry.fColor); |
+ |
+ fPipelineInfo = opt; |
+ } |
+ AAConcavePathBatch(const Geometry& geometry) { |
+ this->initClassID<AAConcavePathBatch>(); |
+ fGeometry = geometry; |
+ geometry.fViewMatrix.mapRect(&fBounds, geometry.fPath.getBounds()); |
+ } |
+ void onPrepareDraws(Target* target) override; |
+ bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; } |
+ |
+ Geometry fGeometry; |
+ GrPipelineOptimizations fPipelineInfo; |
+}; |
+ |
+GrAAConcavePathRenderer::GrAAConcavePathRenderer() { |
+} |
+ |
+ |
+GrPathRenderer::StencilSupport GrAAConcavePathRenderer::onGetStencilSupport( |
+ const SkPath&, |
+ const GrStrokeInfo&) const { |
+ return GrPathRenderer::kNoSupport_StencilSupport; |
+} |
+ |
+bool GrAAConcavePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { |
+ const GrStrokeInfo& stroke = *args.fStroke; |
+ return stroke.isFillStyle(); |
+} |
+ |
+bool GrAAConcavePathRenderer::onDrawPath(const DrawPathArgs& args) { |
+ GrDrawTarget* target = args.fTarget; |
+ |
+ // compute bounds as intersection of rt size, clip, and path |
+ const GrRenderTarget* rt = args.fPipelineBuilder->getRenderTarget(); |
+ if (NULL == rt) { |
+ return false; |
+ } |
+ |
+ SkIRect clipBoundsI; |
+ args.fPipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); |
+ AAConcavePathBatch::Geometry geometry; |
+ geometry.fColor = args.fColor; |
+ geometry.fPath = *args.fPath; |
+ geometry.fViewMatrix = *args.fViewMatrix; |
+ geometry.fClipBounds = clipBoundsI; |
+ geometry.fAntiAlias = args.fAntiAlias; |
+ SkAutoTUnref<GrDrawBatch> batch(AAConcavePathBatch::Create(geometry)); |
+ target->drawBatch(*args.fPipelineBuilder, batch.get()); |
+ |
+ return true; |
+} |
+ |
+void AAConcavePathBatch::onPrepareDraws(Target* target) { |
+ const SkPath& path = fGeometry.fPath; |
+ const SkIRect clipRect = fGeometry.fClipBounds; |
+ const GrColor color = fGeometry.fColor; |
+ const SkMatrix& viewMatrix = fGeometry.fViewMatrix; |
+ bool antiAlias = fGeometry.fAntiAlias; |
+ SkTDArray<SkPoint> points; |
+ SkPath deviceSpacePath; |
+ path.transform(viewMatrix, &deviceSpacePath); |
+ SkScan::PathToTriangles(deviceSpacePath, clipRect, antiAlias, &points); |
+ if (0 == points.count()) { |
+ return; |
+ } |
+ const GrVertexBuffer* vertexBuffer; |
+ int vertexStride = sizeof(SkPoint); |
+ int firstVertex; |
+ void* verts = target->makeVertexSpace(vertexStride, points.count(), &vertexBuffer, &firstVertex); |
+ if (!verts) { |
+ return; |
+ } |
+ |
+ // FIXME: avoid this memcpy by asking SkScan for worst-case size? |
+ memcpy(verts, points.begin(), points.count() * sizeof(SkPoint)); |
+ |
+ // FIXME: pass devBounds here? |
+ uint8_t coverage = 0xFF; |
+ using namespace GrDefaultGeoProcFactory; |
+ LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ? LocalCoords::kUsePosition_Type |
+ : LocalCoords::kUnused_Type); |
+ |
+ GrPrimitiveType primitiveType = SkScan::gWireframe ? kLines_GrPrimitiveType : kTriangles_GrPrimitiveType; |
+ SkAutoTUnref<const GrGeometryProcessor> gp( |
+ GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I())); |
+ |
+ target->initDraw(gp, this->pipeline()); |
+ GrVertices vertices; |
+ vertices.init(primitiveType, vertexBuffer, firstVertex, points.count()); |
+ |
+ target->draw(vertices); |
+} |