Index: src/gpu/GrDrawContext.cpp |
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp |
index 288841c1120abbcb8e61db4d49b447a369d547c3..3ecc8df0727bd9fedacf1a1c082bf906de7e7cd6 100644 |
--- a/src/gpu/GrDrawContext.cpp |
+++ b/src/gpu/GrDrawContext.cpp |
@@ -16,6 +16,7 @@ |
#include "GrPathRenderer.h" |
#include "GrRenderTarget.h" |
#include "GrRenderTargetPriv.h" |
+#include "GrStrokeRectBatch.h" |
#include "GrStencilAndCoverTextContext.h" |
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext) |
@@ -249,183 +250,6 @@ static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& po |
point.fY >= rect.fTop && point.fY <= rect.fBottom; |
} |
-class StrokeRectBatch : public GrBatch { |
-public: |
- struct Geometry { |
- GrColor fColor; |
- SkMatrix fViewMatrix; |
- SkRect fRect; |
- SkScalar fStrokeWidth; |
- }; |
- |
- static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) { |
- return SkNEW_ARGS(StrokeRectBatch, (geometry, snapToPixelCenters)); |
- } |
- |
- const char* name() const override { return "StrokeRectBatch"; } |
- |
- void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
- // When this is called on a batch, there is only one geometry bundle |
- out->setKnownFourComponents(fGeoData[0].fColor); |
- } |
- |
- void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
- out->setKnownSingleComponent(0xff); |
- } |
- |
- void initBatchTracker(const GrPipelineInfo& init) override { |
- // Handle any color overrides |
- if (!init.readsColor()) { |
- fGeoData[0].fColor = GrColor_ILLEGAL; |
- } |
- init.getOverrideColorIfSet(&fGeoData[0].fColor); |
- |
- // setup batch properties |
- fBatch.fColorIgnored = !init.readsColor(); |
- fBatch.fColor = fGeoData[0].fColor; |
- fBatch.fUsesLocalCoords = init.readsLocalCoords(); |
- fBatch.fCoverageIgnored = !init.readsCoverage(); |
- } |
- |
- void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override { |
- SkAutoTUnref<const 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.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoords, |
- this->viewMatrix())); |
- } |
- |
- batchTarget->initDraw(gp, pipeline); |
- |
- size_t vertexStride = gp->getVertexStride(); |
- |
- SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr)); |
- |
- Geometry& args = fGeoData[0]; |
- |
- int vertexCount = kVertsPerHairlineRect; |
- if (args.fStrokeWidth > 0) { |
- vertexCount = kVertsPerStrokeRect; |
- } |
- |
- const GrVertexBuffer* vertexBuffer; |
- int firstVertex; |
- |
- void* verts = batchTarget->makeVertSpace(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; |
- args.fRect.sort(); |
- this->setStrokeRectStrip(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); |
- } |
- |
- GrVertices vertices; |
- vertices.init(primType, vertexBuffer, firstVertex, vertexCount); |
- batchTarget->draw(vertices); |
- } |
- |
- SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
- |
-private: |
- StrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) { |
- this->initClassID<StrokeRectBatch>(); |
- |
- fBatch.fHairline = geometry.fStrokeWidth == 0; |
- |
- fGeoData.push_back(geometry); |
- |
- // setup bounds |
- fBounds = geometry.fRect; |
- SkScalar rad = SkScalarHalf(geometry.fStrokeWidth); |
- fBounds.outset(rad, rad); |
- geometry.fViewMatrix.mapRect(&fBounds); |
- |
- // If our caller snaps to pixel centers then we have to round out the bounds |
- if (snapToPixelCenters) { |
- fBounds.roundOut(); |
- } |
- } |
- |
- /* create a triangle strip that strokes the specified rect. There are 8 |
- unique vertices, but we repeat the last 2 to close up. Alternatively we |
- could use an indices array, and then only send 8 verts, but not sure that |
- would be faster. |
- */ |
- void setStrokeRectStrip(SkPoint verts[10], const SkRect& rect, SkScalar width) { |
- const SkScalar rad = SkScalarHalf(width); |
- // TODO we should be able to enable this assert, but we'd have to filter these draws |
- // this is a bug |
- //SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2); |
- |
- verts[0].set(rect.fLeft + rad, rect.fTop + rad); |
- verts[1].set(rect.fLeft - rad, rect.fTop - rad); |
- verts[2].set(rect.fRight - rad, rect.fTop + rad); |
- verts[3].set(rect.fRight + rad, rect.fTop - rad); |
- verts[4].set(rect.fRight - rad, rect.fBottom - rad); |
- verts[5].set(rect.fRight + rad, rect.fBottom + rad); |
- verts[6].set(rect.fLeft + rad, rect.fBottom - rad); |
- verts[7].set(rect.fLeft - rad, rect.fBottom + rad); |
- verts[8] = verts[0]; |
- verts[9] = verts[1]; |
- } |
- |
- |
- GrColor color() const { return fBatch.fColor; } |
- bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
- bool colorIgnored() const { return fBatch.fColorIgnored; } |
- const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
- bool hairline() const { return fBatch.fHairline; } |
- bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
- |
- bool onCombineIfPossible(GrBatch* t) override { |
- //if (!this->pipeline()->isEqual(*t->pipeline())) { |
- // return false; |
- //} |
- // StrokeRectBatch* that = t->cast<StrokeRectBatch>(); |
- |
- // NonAA stroke rects cannot batch right now |
- // TODO make these batchable |
- return false; |
- } |
- |
- struct BatchTracker { |
- GrColor fColor; |
- bool fUsesLocalCoords; |
- bool fColorIgnored; |
- bool fCoverageIgnored; |
- bool fHairline; |
- }; |
- |
- const static int kVertsPerHairlineRect = 5; |
- const static int kVertsPerStrokeRect = 10; |
- |
- BatchTracker fBatch; |
- SkSTArray<1, Geometry, true> fGeoData; |
-}; |
- |
void GrDrawContext::drawRect(GrRenderTarget* rt, |
const GrClip& clip, |
const GrPaint& paint, |
@@ -513,7 +337,7 @@ void GrDrawContext::drawRect(GrRenderTarget* rt, |
} |
if (width >= 0) { |
- StrokeRectBatch::Geometry geometry; |
+ GrStrokeRectBatch::Geometry geometry; |
geometry.fViewMatrix = viewMatrix; |
geometry.fColor = color; |
geometry.fRect = rect; |
@@ -521,7 +345,7 @@ void GrDrawContext::drawRect(GrRenderTarget* rt, |
// Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic |
bool snapToPixelCenters = (0 == width && !rt->isUnifiedMultisampled()); |
- SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixelCenters)); |
+ SkAutoTUnref<GrBatch> batch(GrStrokeRectBatch::Create(geometry, snapToPixelCenters)); |
// Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of |
// hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA |
@@ -1218,16 +1042,6 @@ void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrBatch* batch |
#ifdef GR_TEST_UTILS |
-BATCH_TEST_DEFINE(StrokeRectBatch) { |
- StrokeRectBatch::Geometry geometry; |
- geometry.fViewMatrix = GrTest::TestMatrix(random); |
- geometry.fColor = GrRandomColor(random); |
- geometry.fRect = GrTest::TestRect(random); |
- geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f; |
- |
- return StrokeRectBatch::Create(geometry, random->nextBool()); |
-} |
- |
static uint32_t seed_vertices(GrPrimitiveType type) { |
switch (type) { |
case kTriangles_GrPrimitiveType: |