Give strokerectbatch a proper home
Review URL: https://codereview.chromium.org/1274763002
This commit is contained in:
parent
847029043e
commit
ee14a622b0
@ -211,6 +211,8 @@
|
||||
'<(skia_src_path)/gpu/GrSoftwarePathRenderer.h',
|
||||
'<(skia_src_path)/gpu/GrSurfacePriv.h',
|
||||
'<(skia_src_path)/gpu/GrSurface.cpp',
|
||||
'<(skia_src_path)/gpu/GrStrokeRectBatch.cpp',
|
||||
'<(skia_src_path)/gpu/GrStrokeRectBatch.h',
|
||||
'<(skia_src_path)/gpu/GrTextBlobCache.cpp',
|
||||
'<(skia_src_path)/gpu/GrTextBlobCache.h',
|
||||
'<(skia_src_path)/gpu/GrTextContext.cpp',
|
||||
|
@ -21,8 +21,8 @@ BATCH_TEST_EXTERN(DefaultPathBatch);
|
||||
BATCH_TEST_EXTERN(CircleBatch);
|
||||
BATCH_TEST_EXTERN(DIEllipseBatch);
|
||||
BATCH_TEST_EXTERN(EllipseBatch);
|
||||
BATCH_TEST_EXTERN(GrStrokeRectBatch);
|
||||
BATCH_TEST_EXTERN(RRectBatch);
|
||||
BATCH_TEST_EXTERN(StrokeRectBatch);
|
||||
BATCH_TEST_EXTERN(TesselatingPathBatch);
|
||||
BATCH_TEST_EXTERN(TextBlobBatch);
|
||||
BATCH_TEST_EXTERN(VerticesBatch);
|
||||
@ -38,8 +38,8 @@ static BatchTestFunc gTestBatches[] = {
|
||||
BATCH_TEST_ENTRY(CircleBatch),
|
||||
BATCH_TEST_ENTRY(DIEllipseBatch),
|
||||
BATCH_TEST_ENTRY(EllipseBatch),
|
||||
BATCH_TEST_ENTRY(GrStrokeRectBatch),
|
||||
BATCH_TEST_ENTRY(RRectBatch),
|
||||
BATCH_TEST_ENTRY(StrokeRectBatch),
|
||||
BATCH_TEST_ENTRY(TesselatingPathBatch),
|
||||
BATCH_TEST_ENTRY(TextBlobBatch),
|
||||
BATCH_TEST_ENTRY(VerticesBatch)
|
||||
|
@ -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)
|
||||
@ -235,183 +236,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,
|
||||
@ -499,7 +323,7 @@ void GrDrawContext::drawRect(GrRenderTarget* rt,
|
||||
}
|
||||
|
||||
if (width >= 0) {
|
||||
StrokeRectBatch::Geometry geometry;
|
||||
GrStrokeRectBatch::Geometry geometry;
|
||||
geometry.fViewMatrix = viewMatrix;
|
||||
geometry.fColor = color;
|
||||
geometry.fRect = rect;
|
||||
@ -507,7 +331,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
|
||||
@ -1204,16 +1028,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:
|
||||
|
24
src/gpu/GrStrokeRectBatch.cpp
Normal file
24
src/gpu/GrStrokeRectBatch.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 "SkRandom.h"
|
||||
|
||||
#ifdef GR_TEST_UTILS
|
||||
|
||||
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
|
192
src/gpu/GrStrokeRectBatch.h
Normal file
192
src/gpu/GrStrokeRectBatch.h
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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 "GrBatch.h"
|
||||
#include "GrColor.h"
|
||||
#include "GrDefaultGeoProcFactory.h"
|
||||
|
||||
class GrStrokeRectBatch : public GrBatch {
|
||||
public:
|
||||
struct Geometry {
|
||||
GrColor fColor;
|
||||
SkMatrix fViewMatrix;
|
||||
SkRect fRect;
|
||||
SkScalar fStrokeWidth;
|
||||
};
|
||||
|
||||
static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) {
|
||||
return SkNEW_ARGS(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);
|
||||
}
|
||||
|
||||
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:
|
||||
GrStrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) {
|
||||
this->initClassID<GrStrokeRectBatch>();
|
||||
|
||||
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;
|
||||
//}
|
||||
// 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;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user