Move StrokeRectBatches into .cpp files

BUG=skia:

Review URL: https://codereview.chromium.org/1353683003
This commit is contained in:
joshualitt 2015-09-18 07:12:55 -07:00 committed by Commit bot
parent 966e3d30ba
commit 3566d44d85
12 changed files with 476 additions and 424 deletions

View File

@ -226,10 +226,10 @@
'<(skia_src_path)/gpu/batches/GrDrawVerticesBatch.h',
'<(skia_src_path)/gpu/batches/GrNonAAFillRectBatch.h',
'<(skia_src_path)/gpu/batches/GrNonAAFillRectBatch.cpp',
'<(skia_src_path)/gpu/batches/GrNonAAStrokeRectBatch.cpp',
'<(skia_src_path)/gpu/batches/GrNonAAStrokeRectBatch.h',
'<(skia_src_path)/gpu/batches/GrRectBatchFactory.h',
'<(skia_src_path)/gpu/batches/GrRectBatchFactory.cpp',
'<(skia_src_path)/gpu/batches/GrStrokeRectBatch.cpp',
'<(skia_src_path)/gpu/batches/GrStrokeRectBatch.h',
'<(skia_src_path)/gpu/batches/GrStencilAndCoverPathRenderer.cpp',
'<(skia_src_path)/gpu/batches/GrStencilAndCoverPathRenderer.h',
'<(skia_src_path)/gpu/batches/GrStencilPathBatch.h',

View File

@ -23,7 +23,7 @@ DRAW_BATCH_TEST_EXTERN(CircleBatch);
DRAW_BATCH_TEST_EXTERN(DIEllipseBatch);
DRAW_BATCH_TEST_EXTERN(EllipseBatch);
DRAW_BATCH_TEST_EXTERN(GrDrawAtlasBatch);
DRAW_BATCH_TEST_EXTERN(GrStrokeRectBatch);
DRAW_BATCH_TEST_EXTERN(NonAAStrokeRectBatch);
DRAW_BATCH_TEST_EXTERN(RRectBatch);
DRAW_BATCH_TEST_EXTERN(TesselatingPathBatch);
DRAW_BATCH_TEST_EXTERN(TextBlobBatch);
@ -42,7 +42,7 @@ static BatchTestFunc gTestBatches[] = {
DRAW_BATCH_TEST_ENTRY(DIEllipseBatch),
DRAW_BATCH_TEST_ENTRY(EllipseBatch),
DRAW_BATCH_TEST_ENTRY(GrDrawAtlasBatch),
DRAW_BATCH_TEST_ENTRY(GrStrokeRectBatch),
DRAW_BATCH_TEST_ENTRY(NonAAStrokeRectBatch),
DRAW_BATCH_TEST_ENTRY(RRectBatch),
DRAW_BATCH_TEST_ENTRY(TesselatingPathBatch),
DRAW_BATCH_TEST_ENTRY(TextBlobBatch),

View File

@ -43,7 +43,111 @@ static const GrGeometryProcessor* create_stroke_rect_gp(bool tweakAlphaForCovera
return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix);
}
void GrAAStrokeRectBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
class AAStrokeRectBatch : public GrVertexBatch {
public:
DEFINE_BATCH_CLASS_ID
// TODO support AA rotated stroke rects by copying around view matrices
struct Geometry {
SkRect fDevOutside;
SkRect fDevOutsideAssist;
SkRect fDevInside;
GrColor fColor;
bool fMiterStroke;
};
static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& devOutside,
const SkRect& devOutsideAssist, const SkRect& devInside,
bool miterStroke) {
return new AAStrokeRectBatch(color, viewMatrix, devOutside, devOutsideAssist, devInside,
miterStroke);
}
const char* name() const override { return "AAStrokeRect"; }
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->setUnknownSingleComponent();
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
private:
void onPrepareDraws(Target*) override;
void initBatchTracker(const GrPipelineOptimizations&) override;
AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& devOutside,
const SkRect& devOutsideAssist, const SkRect& devInside, bool miterStroke)
: INHERITED(ClassID()) {
fBatch.fViewMatrix = viewMatrix;
Geometry& geometry = fGeoData.push_back();
geometry.fColor = color;
geometry.fDevOutside = devOutside;
geometry.fDevOutsideAssist = devOutsideAssist;
geometry.fDevInside = devInside;
geometry.fMiterStroke = miterStroke;
// If we have miterstroke then we inset devOutside and outset devOutsideAssist, so we need
// the join for proper bounds
fBounds = geometry.fDevOutside;
fBounds.join(geometry.fDevOutsideAssist);
}
static const int kMiterIndexCnt = 3 * 24;
static const int kMiterVertexCnt = 16;
static const int kNumMiterRectsInIndexBuffer = 256;
static const int kBevelIndexCnt = 48 + 36 + 24;
static const int kBevelVertexCnt = 24;
static const int kNumBevelRectsInIndexBuffer = 256;
static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider,
bool miterStroke);
GrColor color() const { return fBatch.fColor; }
bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
bool colorIgnored() const { return fBatch.fColorIgnored; }
const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
bool miterStroke() const { return fBatch.fMiterStroke; }
bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
bool onCombineIfPossible(GrBatch* t, const GrCaps&) override;
void generateAAStrokeRectGeometry(void* vertices,
size_t offset,
size_t vertexStride,
int outerVertexNum,
int innerVertexNum,
GrColor color,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke,
bool tweakAlphaForCoverage) const;
struct BatchTracker {
SkMatrix fViewMatrix;
GrColor fColor;
bool fUsesLocalCoords;
bool fColorIgnored;
bool fCoverageIgnored;
bool fMiterStroke;
bool fCanTweakAlphaForCoverage;
};
BatchTracker fBatch;
SkSTArray<1, Geometry, true> fGeoData;
typedef GrVertexBatch INHERITED;
};
void AAStrokeRectBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
// Handle any color overrides
if (!opt.readsColor()) {
fGeoData[0].fColor = GrColor_ILLEGAL;
@ -59,7 +163,7 @@ void GrAAStrokeRectBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage();
}
void GrAAStrokeRectBatch::onPrepareDraws(Target* target) {
void AAStrokeRectBatch::onPrepareDraws(Target* target) {
bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage();
SkAutoTUnref<const GrGeometryProcessor> gp(create_stroke_rect_gp(canTweakAlphaForCoverage,
@ -112,8 +216,8 @@ void GrAAStrokeRectBatch::onPrepareDraws(Target* target) {
helper.recordDraw(target);
}
const GrIndexBuffer* GrAAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resourceProvider,
bool miterStroke) {
const GrIndexBuffer* AAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resourceProvider,
bool miterStroke) {
if (miterStroke) {
static const uint16_t gMiterIndices[] = {
@ -203,8 +307,8 @@ const GrIndexBuffer* GrAAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* res
}
}
bool GrAAStrokeRectBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) {
GrAAStrokeRectBatch* that = t->cast<GrAAStrokeRectBatch>();
bool AAStrokeRectBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) {
AAStrokeRectBatch* that = t->cast<AAStrokeRectBatch>();
if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
that->bounds(), caps)) {
@ -237,17 +341,17 @@ bool GrAAStrokeRectBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) {
return true;
}
void GrAAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices,
size_t offset,
size_t vertexStride,
int outerVertexNum,
int innerVertexNum,
GrColor color,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke,
bool tweakAlphaForCoverage) const {
void AAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices,
size_t offset,
size_t vertexStride,
int outerVertexNum,
int innerVertexNum,
GrColor color,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke,
bool tweakAlphaForCoverage) const {
intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset;
// We create vertices for four nested rectangles. There are two ramps from 0 to full
@ -350,6 +454,20 @@ void GrAAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices,
}
}
namespace GrAAStrokeRectBatch {
GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke) {
return AAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutsideAssist, devInside,
miterStroke);
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef GR_TEST_UTILS
@ -368,14 +486,10 @@ DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) {
SkRect inside = outside;
inside.inset(strokeWidth, strokeWidth);
GrAAStrokeRectBatch::Geometry geo;
geo.fColor = GrRandomColor(random);
geo.fDevOutside = outside;
geo.fDevOutsideAssist = outsideAssist;
geo.fDevInside = inside;
geo.fMiterStroke = miterStroke;
GrColor color = GrRandomColor(random);
return GrAAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random));
return GrAAStrokeRectBatch::Create(color, GrTest::TestMatrix(random), outside, outsideAssist,
inside, miterStroke);
}
#endif

View File

@ -9,107 +9,21 @@
#define GrAAStrokeRectBatch_DEFINED
#include "GrColor.h"
#include "GrTypes.h"
#include "GrVertexBatch.h"
#include "SkMatrix.h"
#include "SkRect.h"
class GrDrawBatch;
class GrResourceProvider;
class SkMatrix;
struct SkRect;
class GrAAStrokeRectBatch : public GrVertexBatch {
public:
DEFINE_BATCH_CLASS_ID
namespace GrAAStrokeRectBatch {
// TODO support AA rotated stroke rects by copying around view matrices
struct Geometry {
GrColor fColor;
SkRect fDevOutside;
SkRect fDevOutsideAssist;
SkRect fDevInside;
bool fMiterStroke;
};
GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke);
static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix) {
return new GrAAStrokeRectBatch(geometry, viewMatrix);
}
const char* name() const override { return "AAStrokeRect"; }
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->setUnknownSingleComponent();
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
private:
void onPrepareDraws(Target*) override;
void initBatchTracker(const GrPipelineOptimizations&) override;
GrAAStrokeRectBatch(const Geometry& geometry, const SkMatrix& viewMatrix)
: INHERITED(ClassID()) {
fBatch.fViewMatrix = viewMatrix;
fGeoData.push_back(geometry);
// If we have miterstroke then we inset devOutside and outset devOutsideAssist, so we need
// the join for proper bounds
fBounds = geometry.fDevOutside;
fBounds.join(geometry.fDevOutsideAssist);
}
static const int kMiterIndexCnt = 3 * 24;
static const int kMiterVertexCnt = 16;
static const int kNumMiterRectsInIndexBuffer = 256;
static const int kBevelIndexCnt = 48 + 36 + 24;
static const int kBevelVertexCnt = 24;
static const int kNumBevelRectsInIndexBuffer = 256;
static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider,
bool miterStroke);
GrColor color() const { return fBatch.fColor; }
bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
bool colorIgnored() const { return fBatch.fColorIgnored; }
const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
bool miterStroke() const { return fBatch.fMiterStroke; }
bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
bool onCombineIfPossible(GrBatch* t, const GrCaps&) override;
void generateAAStrokeRectGeometry(void* vertices,
size_t offset,
size_t vertexStride,
int outerVertexNum,
int innerVertexNum,
GrColor color,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke,
bool tweakAlphaForCoverage) const;
struct BatchTracker {
SkMatrix fViewMatrix;
GrColor fColor;
bool fUsesLocalCoords;
bool fColorIgnored;
bool fCoverageIgnored;
bool fMiterStroke;
bool fCanTweakAlphaForCoverage;
};
BatchTracker fBatch;
SkSTArray<1, Geometry, true> fGeoData;
typedef GrVertexBatch INHERITED;
};
#endif

View File

@ -188,54 +188,59 @@ typedef GrTInstanceBatch<NonAAFillRectBatchImp> NonAAFillRectBatchSimple;
typedef GrTInstanceBatch<NonAAFillRectBatchPerspectiveImp> NonAAFillRectBatchPerspective;
namespace GrNonAAFillRectBatch {
GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix) {
SkASSERT(!viewMatrix.hasPerspective() && (!localMatrix || !localMatrix->hasPerspective()));
NonAAFillRectBatchSimple* batch = NonAAFillRectBatchSimple::Create();
NonAAFillRectBatchSimple::Geometry& geo = *batch->geometry();
/* Perspective has to be handled in a slow path for now */
if (viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective())) {
NonAAFillRectBatchPerspective* batch = NonAAFillRectBatchPerspective::Create();
NonAAFillRectBatchPerspective::Geometry& geo = *batch->geometry();
geo.fColor = color;
geo.fViewMatrix = viewMatrix;
geo.fRect = rect;
geo.fColor = color;
geo.fViewMatrix = viewMatrix;
geo.fRect = rect;
geo.fHasLocalRect = SkToBool(localRect);
geo.fHasLocalMatrix = SkToBool(localMatrix);
if (localMatrix) {
geo.fLocalMatrix = *localMatrix;
}
if (localRect) {
geo.fLocalRect = *localRect;
}
batch->init();
return batch;
if (localRect && localMatrix) {
geo.fLocalQuad.setFromMappedRect(*localRect, *localMatrix);
} else if (localRect) {
geo.fLocalQuad.set(*localRect);
} else if (localMatrix) {
geo.fLocalQuad.setFromMappedRect(rect, *localMatrix);
} else {
// TODO bubble these up as separate calls
NonAAFillRectBatchSimple* batch = NonAAFillRectBatchSimple::Create();
NonAAFillRectBatchSimple::Geometry& geo = *batch->geometry();
geo.fColor = color;
geo.fViewMatrix = viewMatrix;
geo.fRect = rect;
if (localRect && localMatrix) {
geo.fLocalQuad.setFromMappedRect(*localRect, *localMatrix);
} else if (localRect) {
geo.fLocalQuad.set(*localRect);
} else if (localMatrix) {
geo.fLocalQuad.setFromMappedRect(rect, *localMatrix);
} else {
geo.fLocalQuad.set(rect);
}
batch->init();
return batch;
geo.fLocalQuad.set(rect);
}
batch->init();
return batch;
}
GrDrawBatch* CreateWithPerspective(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix) {
SkASSERT(viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective()));
NonAAFillRectBatchPerspective* batch = NonAAFillRectBatchPerspective::Create();
NonAAFillRectBatchPerspective::Geometry& geo = *batch->geometry();
geo.fColor = color;
geo.fViewMatrix = viewMatrix;
geo.fRect = rect;
geo.fHasLocalRect = SkToBool(localRect);
geo.fHasLocalMatrix = SkToBool(localMatrix);
if (localMatrix) {
geo.fLocalMatrix = *localMatrix;
}
if (localRect) {
geo.fLocalRect = *localRect;
}
batch->init();
return batch;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -15,11 +15,19 @@ class SkMatrix;
struct SkRect;
namespace GrNonAAFillRectBatch {
GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix);
GrDrawBatch* CreateWithPerspective(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix);
};
#endif

View File

@ -0,0 +1,226 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrNonAAStrokeRectBatch.h"
#include "GrBatchTest.h"
#include "GrBatchFlushState.h"
#include "GrColor.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrVertexBatch.h"
#include "SkRandom.h"
/* 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.
*/
static void init_stroke_rect_strip(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];
}
class NonAAStrokeRectBatch : public GrVertexBatch {
public:
DEFINE_BATCH_CLASS_ID
struct Geometry {
SkMatrix fViewMatrix;
SkRect fRect;
SkScalar fStrokeWidth;
GrColor fColor;
};
static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
SkScalar strokeWidth, bool snapToPixelCenters) {
return new NonAAStrokeRectBatch(color, viewMatrix, rect, strokeWidth, snapToPixelCenters);
}
const char* name() const override { return "GrStrokeRectBatch"; }
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);
}
private:
void onPrepareDraws(Target* target) 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()));
}
target->initDraw(gp, this->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 = target->makeVertexSpace(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();
init_stroke_rect_strip(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);
target->draw(vertices);
}
void initBatchTracker(const GrPipelineOptimizations& opt) override {
// Handle any color overrides
if (!opt.readsColor()) {
fGeoData[0].fColor = GrColor_ILLEGAL;
}
opt.getOverrideColorIfSet(&fGeoData[0].fColor);
// setup batch properties
fBatch.fColorIgnored = !opt.readsColor();
fBatch.fColor = fGeoData[0].fColor;
fBatch.fUsesLocalCoords = opt.readsLocalCoords();
fBatch.fCoverageIgnored = !opt.readsCoverage();
}
NonAAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
SkScalar strokeWidth, bool snapToPixelCenters)
: INHERITED(ClassID()) {
Geometry& geometry = fGeoData.push_back();
geometry.fViewMatrix = viewMatrix;
geometry.fRect = rect;
geometry.fStrokeWidth = strokeWidth;
geometry.fColor = color;
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();
}
}
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, const GrCaps&) override {
// if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *t->pipeline(),
// t->bounds(), caps)) {
// return false;
// }
// GrStrokeRectBatch* 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;
typedef GrVertexBatch INHERITED;
};
namespace GrNonAAStrokeRectBatch {
GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
SkScalar strokeWidth,
bool snapToPixelCenters) {
return NonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeWidth, snapToPixelCenters);
}
};
#ifdef GR_TEST_UTILS
DRAW_BATCH_TEST_DEFINE(NonAAStrokeRectBatch) {
SkMatrix viewMatrix = GrTest::TestMatrix(random);
GrColor color = GrRandomColor(random);
SkRect rect = GrTest::TestRect(random);
SkScalar strokeWidth = random->nextBool() ? 0.0f : 1.0f;
return NonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeWidth, random->nextBool());
}
#endif

View File

@ -0,0 +1,29 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrNonAAStrokeRectBatch_DEFINED
#define GrNonAAStrokeRectBatch_DEFINED
#include "GrColor.h"
#include "SkTypes.h"
class GrDrawBatch;
struct SkRect;
class SkMatrix;
namespace GrNonAAStrokeRectBatch {
GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
SkScalar strokeWidth,
bool snapToPixelCenters);
};
#endif

View File

@ -8,41 +8,11 @@
#include "GrRectBatchFactory.h"
#include "GrAAStrokeRectBatch.h"
#include "GrStrokeRectBatch.h"
#include "SkStrokeRec.h"
static GrDrawBatch* create_stroke_aa_batch(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool miterStroke) {
GrAAStrokeRectBatch::Geometry geometry;
geometry.fColor = color;
geometry.fDevOutside = devOutside;
geometry.fDevOutsideAssist = devOutsideAssist;
geometry.fDevInside = devInside;
geometry.fMiterStroke = miterStroke;
return GrAAStrokeRectBatch::Create(geometry, viewMatrix);
}
namespace GrRectBatchFactory {
GrDrawBatch* CreateNonAAStroke(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
SkScalar strokeWidth,
bool snapToPixelCenters) {
GrStrokeRectBatch::Geometry geometry;
geometry.fColor = color;
geometry.fViewMatrix = viewMatrix;
geometry.fRect = rect;
geometry.fStrokeWidth = strokeWidth;
return GrStrokeRectBatch::Create(geometry, snapToPixelCenters);
}
GrDrawBatch* CreateAAStroke(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
@ -98,8 +68,8 @@ GrDrawBatch* CreateAAStroke(GrColor color,
devOutsideAssist.outset(0, ry);
}
return create_stroke_aa_batch(color, viewMatrix, devOutside, devOutsideAssist, devInside,
miterStroke);
return GrAAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutsideAssist, devInside,
miterStroke);
}
GrDrawBatch* CreateAAFillNestedRects(GrColor color,
@ -116,7 +86,7 @@ GrDrawBatch* CreateAAFillNestedRects(GrColor color,
return CreateAAFill(color, viewMatrix, devOutside, devOutside);
}
return create_stroke_aa_batch(color, viewMatrix, devOutside, devOutside, devInside, true);
return GrAAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutside, devInside, true);
}
};

View File

@ -11,9 +11,10 @@
#include "GrAAFillRectBatch.h"
#include "GrColor.h"
#include "GrNonAAFillRectBatch.h"
#include "GrNonAAStrokeRectBatch.h"
#include "SkMatrix.h"
class GrBatch;
class SkMatrix;
struct SkRect;
class SkStrokeRec;
@ -27,7 +28,12 @@ inline GrDrawBatch* CreateNonAAFill(GrColor color,
const SkRect& rect,
const SkRect* localRect,
const SkMatrix* localMatrix) {
return GrNonAAFillRectBatch::Create(color, viewMatrix, rect, localRect, localMatrix);
if (viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective())) {
return GrNonAAFillRectBatch::CreateWithPerspective(color, viewMatrix, rect, localRect,
localMatrix);
} else {
return GrNonAAFillRectBatch::Create(color, viewMatrix, rect, localRect, localMatrix);
}
}
inline GrDrawBatch* CreateAAFill(GrColor color,
@ -45,11 +51,13 @@ inline GrDrawBatch* CreateAAFill(GrColor color,
return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRect);
}
GrDrawBatch* CreateNonAAStroke(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
SkScalar strokeWidth,
bool snapToPixelCenters);
inline GrDrawBatch* CreateNonAAStroke(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
SkScalar strokeWidth,
bool snapToPixelCenters) {
return GrNonAAStrokeRectBatch::Create(color, viewMatrix, rect, strokeWidth, snapToPixelCenters);
}
GrDrawBatch* CreateAAStroke(GrColor,
const SkMatrix& viewMatrix,

View File

@ -1,139 +0,0 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrStrokeRectBatch.h"
#include "GrBatchTest.h"
#include "GrBatchFlushState.h"
#include "SkRandom.h"
GrStrokeRectBatch::GrStrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters)
: INHERITED(ClassID()) {
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();
}
}
void GrStrokeRectBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
// Handle any color overrides
if (!opt.readsColor()) {
fGeoData[0].fColor = GrColor_ILLEGAL;
}
opt.getOverrideColorIfSet(&fGeoData[0].fColor);
// setup batch properties
fBatch.fColorIgnored = !opt.readsColor();
fBatch.fColor = fGeoData[0].fColor;
fBatch.fUsesLocalCoords = opt.readsLocalCoords();
fBatch.fCoverageIgnored = !opt.readsCoverage();
}
/* 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.
*/
static void init_stroke_rect_strip(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];
}
void GrStrokeRectBatch::onPrepareDraws(Target* target) {
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()));
}
target->initDraw(gp, this->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 = target->makeVertexSpace(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();
init_stroke_rect_strip(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);
target->draw(vertices);
}
#ifdef GR_TEST_UTILS
DRAW_BATCH_TEST_DEFINE(GrStrokeRectBatch) {
GrStrokeRectBatch::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 GrStrokeRectBatch::Create(geometry, random->nextBool());
}
#endif

View File

@ -1,83 +0,0 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrStrokeRectBatch_DEFINED
#define GrStrokeRectBatch_DEFINED
#include "GrColor.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrVertexBatch.h"
class GrStrokeRectBatch : public GrVertexBatch {
public:
DEFINE_BATCH_CLASS_ID
struct Geometry {
GrColor fColor;
SkMatrix fViewMatrix;
SkRect fRect;
SkScalar fStrokeWidth;
};
static GrDrawBatch* Create(const Geometry& geometry, bool snapToPixelCenters) {
return new GrStrokeRectBatch(geometry, snapToPixelCenters);
}
const char* name() const override { return "GrStrokeRectBatch"; }
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);
}
private:
void onPrepareDraws(Target*) override;
void initBatchTracker(const GrPipelineOptimizations&) override;
GrStrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters);
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, const GrCaps&) override {
// if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *t->pipeline(),
// t->bounds(), caps)) {
// return false;
// }
// GrStrokeRectBatch* 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;
typedef GrVertexBatch INHERITED;
};
#endif