Start on simplifying generateGeometry() overrides

Review URL: https://codereview.chromium.org/1122673002
This commit is contained in:
bsalomon 2015-05-04 11:27:45 -07:00 committed by Commit bot
parent b327c3a84a
commit f28381c686
17 changed files with 434 additions and 735 deletions

View File

@ -16,7 +16,6 @@
#include "GrBufferAllocPool.h"
#include "GrContext.h"
#include "GrPathUtils.h"
#include "GrResourceProvider.h"
#include "GrTest.h"
#include "GrTestBatch.h"
#include "SkColorPriv.h"
@ -67,25 +66,14 @@ private:
}
void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
QuadHelper helper;
size_t vertexStride = this->geometryProcessor()->getVertexStride();
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
kVertsPerCubic,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
SkASSERT(vertexStride == sizeof(Vertex));
Vertex* verts = reinterpret_cast<Vertex*>(helper.init(batchTarget, vertexStride, 1));
if (!verts) {
return;
}
SkASSERT(vertexStride == sizeof(Vertex));
Vertex* verts = reinterpret_cast<Vertex*>(vertices);
verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop,
fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
sizeof(Vertex));
@ -94,16 +82,7 @@ private:
verts[v].fKLM[1] = eval_line(verts[v].fPosition, fKlmEqs + 3, fSign);
verts[v].fKLM[2] = eval_line(verts[v].fPosition, fKlmEqs + 6, 1.f);
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangleFan_GrPrimitiveType);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(kVertsPerCubic);
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(kIndicesPerCubic);
drawInfo.setIndexBuffer(indexBuffer);
batchTarget->draw(drawInfo);
helper.issueDraws(batchTarget);
}
Geometry fGeometry;
@ -475,42 +454,19 @@ private:
}
void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
QuadHelper helper;
size_t vertexStride = this->geometryProcessor()->getVertexStride();
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
kVertsPerCubic,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
SkASSERT(vertexStride == sizeof(Vertex));
GrDrawTarget::DrawInfo drawInfo;
Vertex* verts = reinterpret_cast<Vertex*>(helper.init(batchTarget, vertexStride, 1));
if (!verts) {
return;
}
SkASSERT(vertexStride == sizeof(Vertex));
Vertex* verts = reinterpret_cast<Vertex*>(vertices);
verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop,
fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
sizeof(Vertex));
fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(kVertsPerCubic);
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(kIndicesPerCubic);
drawInfo.setIndexBuffer(indexBuffer);
batchTarget->draw(drawInfo);
helper.issueDraws(batchTarget);
}
Geometry fGeometry;

View File

@ -17,7 +17,6 @@
#include "GrContext.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrPathUtils.h"
#include "GrResourceProvider.h"
#include "GrTest.h"
#include "GrTestBatch.h"
#include "SkColorPriv.h"
@ -53,47 +52,24 @@ private:
}
void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
size_t vertexStride = this->geometryProcessor()->getVertexStride();
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
kVertsPerCubic,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
SkASSERT(vertexStride == sizeof(SkPoint));
QuadHelper helper;
SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(batchTarget, vertexStride, 1));
if (!verts) {
return;
}
SkASSERT(vertexStride == sizeof(SkPoint));
SkPoint* verts = reinterpret_cast<SkPoint*>(vertices);
// Make sure any artifacts around the exterior of path are visible by using overly
// conservative bounding geometry.
fGeometry.fBounds.outset(5.f, 5.f);
fGeometry.fBounds.toQuad(verts);
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangleFan_GrPrimitiveType);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(kVertsPerCubic);
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(kIndicesPerCubic);
drawInfo.setIndexBuffer(indexBuffer);
batchTarget->draw(drawInfo);
helper.issueDraws(batchTarget);
}
Geometry fGeometry;
static const int kVertsPerCubic = 4;
static const int kIndicesPerCubic = 6;
typedef GrTestBatch INHERITED;
};

View File

@ -824,19 +824,14 @@ public:
create_vertices(segments, fanPt, &draws, verts, idxs);
GrDrawTarget::DrawInfo info;
info.setVertexBuffer(vertexBuffer);
info.setIndexBuffer(indexBuffer);
info.setPrimitiveType(kTriangles_GrPrimitiveType);
info.setStartIndex(firstIndex);
int vOffset = 0;
for (int i = 0; i < draws.count(); ++i) {
const Draw& draw = draws[i];
info.setStartVertex(vOffset + firstVertex);
info.setVertexCount(draw.fVertexCnt);
info.setIndexCount(draw.fIndexCnt);
info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex,
firstIndex, draw.fVertexCnt, draw.fIndexCnt);
batchTarget->draw(info);
vOffset += draw.fVertexCnt;
firstVertex += draw.fVertexCnt;
firstIndex += draw.fIndexCnt;
}
}
}

View File

@ -13,9 +13,9 @@
#include "GrBufferAllocPool.h"
#include "GrContext.h"
#include "GrPipelineBuilder.h"
#include "GrResourceProvider.h"
#include "GrSurfacePriv.h"
#include "GrSWMaskHelper.h"
#include "GrResourceProvider.h"
#include "GrTexturePriv.h"
#include "GrVertexBuffer.h"
#include "effects/GrDistanceFieldGeoProc.h"
@ -169,6 +169,13 @@ public:
fBatch.fCoverageIgnored = init.fCoverageIgnored;
}
struct FlushInfo {
SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
int fVertexOffset;
int fInstancesToFlush;
};
void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
int instanceCount = fGeoData.count();
@ -195,43 +202,25 @@ public:
this->initDraw(batchTarget, dfProcessor, pipeline);
static const int kVertsPerQuad = 4;
static const int kIndicesPerQuad = 6;
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
FlushInfo flushInfo;
// allocate vertices
size_t vertexStride = dfProcessor->getVertexStride();
SkASSERT(vertexStride == 2 * sizeof(SkPoint));
const GrVertexBuffer* vertexBuffer;
int vertexCount = kVertsPerQuad * instanceCount;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
kVerticesPerQuad * instanceCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
&flushInfo.fVertexOffset);
flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
flushInfo.fIndexBuffer.reset(batchTarget->resourceProvider()->refQuadIndexBuffer());
if (!vertices || !flushInfo.fIndexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
// We may have to flush while uploading path data to the atlas, so we set up the draw here
int maxInstancesPerDraw = indexBuffer->maxQuads();
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerQuad);
drawInfo.setIndicesPerInstance(kIndicesPerQuad);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int instancesToFlush = 0;
flushInfo.fInstancesToFlush = 0;
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
@ -265,9 +254,7 @@ public:
if (!this->addPathToAtlas(batchTarget,
dfProcessor,
pipeline,
&drawInfo,
&instancesToFlush,
maxInstancesPerDraw,
&flushInfo,
atlas,
args.fPathData,
args.fPath,
@ -284,21 +271,21 @@ public:
// Now set vertices
intptr_t offset = reinterpret_cast<intptr_t>(vertices);
offset += i * kVertsPerQuad * vertexStride;
offset += i * kVerticesPerQuad * vertexStride;
SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
this->drawPath(batchTarget,
atlas,
pipeline,
dfProcessor,
positions,
vertexStride,
this->viewMatrix(),
args.fPath,
args.fPathData);
instancesToFlush++;
this->writePathVertices(batchTarget,
atlas,
pipeline,
dfProcessor,
positions,
vertexStride,
this->viewMatrix(),
args.fPath,
args.fPathData);
flushInfo.fInstancesToFlush++;
}
this->flush(batchTarget, &drawInfo, instancesToFlush, maxInstancesPerDraw);
this->flush(batchTarget, &flushInfo);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -325,9 +312,7 @@ private:
bool addPathToAtlas(GrBatchTarget* batchTarget,
const GrGeometryProcessor* dfProcessor,
const GrPipeline* pipeline,
GrDrawTarget::DrawInfo* drawInfo,
int* instancesToFlush,
int maxInstancesPerDraw,
FlushInfo* flushInfo,
GrBatchAtlas* atlas,
PathData* pathData,
const SkPath& path,
@ -429,9 +414,8 @@ private:
bool success = atlas->addToAtlas(&id, batchTarget, width, height, dfStorage.get(),
&atlasLocation);
if (!success) {
this->flush(batchTarget, drawInfo, *instancesToFlush, maxInstancesPerDraw);
this->flush(batchTarget, flushInfo);
this->initDraw(batchTarget, dfProcessor, pipeline);
*instancesToFlush = 0;
SkDEBUGCODE(success =) atlas->addToAtlas(&id, batchTarget, width, height,
dfStorage.get(), &atlasLocation);
@ -467,15 +451,15 @@ private:
return true;
}
void drawPath(GrBatchTarget* target,
GrBatchAtlas* atlas,
const GrPipeline* pipeline,
const GrGeometryProcessor* gp,
SkPoint* positions,
size_t vertexStride,
const SkMatrix& viewMatrix,
const SkPath& path,
const PathData* pathData) {
void writePathVertices(GrBatchTarget* target,
GrBatchAtlas* atlas,
const GrPipeline* pipeline,
const GrGeometryProcessor* gp,
SkPoint* positions,
size_t vertexStride,
const SkMatrix& viewMatrix,
const SkPath& path,
const PathData* pathData) {
GrTexture* texture = atlas->getTexture();
SkScalar dx = pathData->fBounds.fLeft;
@ -522,20 +506,18 @@ private:
dfProcessor->initBatchTracker(batchTarget->currentBatchTracker(), init);
}
void flush(GrBatchTarget* batchTarget,
GrDrawTarget::DrawInfo* drawInfo,
int instanceCount,
int maxInstancesPerDraw) {
while (instanceCount) {
drawInfo->setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo->setVertexCount(drawInfo->instanceCount() * drawInfo->verticesPerInstance());
drawInfo->setIndexCount(drawInfo->instanceCount() * drawInfo->indicesPerInstance());
batchTarget->draw(*drawInfo);
drawInfo->setStartVertex(drawInfo->startVertex() + drawInfo->vertexCount());
instanceCount -= drawInfo->instanceCount();
}
void flush(GrBatchTarget* batchTarget, FlushInfo* flushInfo) {
GrDrawTarget::DrawInfo drawInfo;
int instancesToFlush = flushInfo->fInstancesToFlush;
int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads();
drawInfo.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad,
kIndicesPerQuad, &instancesToFlush, maxInstancesPerDraw);
do {
batchTarget->draw(drawInfo);
} while (drawInfo.nextInstances(&instancesToFlush, maxInstancesPerDraw));
flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush;
flushInfo->fInstancesToFlush = 0;
}
GrColor color() const { return fBatch.fColor; }

View File

@ -888,23 +888,14 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
}
{
int linesLeft = lineCount;
GrDrawTarget::DrawInfo info;
info.setVertexBuffer(vertexBuffer);
info.setIndexBuffer(linesIndexBuffer);
info.setPrimitiveType(kTriangles_GrPrimitiveType);
info.setStartIndex(0);
int lines = 0;
while (lines < lineCount) {
int n = SkTMin(lineCount - lines, kLineSegsNumInIdxBuffer);
info.setStartVertex(kLineSegNumVertices*lines + firstVertex);
info.setVertexCount(kLineSegNumVertices*n);
info.setIndexCount(kIdxsPerLineSeg*n);
info.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, linesIndexBuffer,
firstVertex, kLineSegNumVertices, kIdxsPerLineSeg, &linesLeft,
kLineSegsNumInIdxBuffer);
do {
batchTarget->draw(info);
lines += n;
}
} while (info.nextInstances(&linesLeft, kLineSegsNumInIdxBuffer));
}
}
@ -953,23 +944,15 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
quadGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
{
GrDrawTarget::DrawInfo info;
info.setVertexBuffer(vertexBuffer);
info.setIndexBuffer(quadsIndexBuffer);
info.setPrimitiveType(kTriangles_GrPrimitiveType);
info.setStartIndex(0);
int quads = 0;
while (quads < quadCount) {
int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer);
info.setStartVertex(kQuadNumVertices*quads + firstVertex);
info.setVertexCount(kQuadNumVertices*n);
info.setIndexCount(kIdxsPerQuad*n);
int quadsLeft = quadCount;
GrDrawTarget::DrawInfo info;
info.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
firstVertex, kQuadNumVertices, kIdxsPerQuad, &quadsLeft,
kQuadsNumInIdxBuffer);
do {
batchTarget->draw(info);
quads += n;
}
} while (info.nextInstances(&quadsLeft, kQuadsNumInIdxBuffer));
firstVertex += quadCount * kQuadNumVertices;
}
}
@ -985,23 +968,14 @@ void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel
conicGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
{
int conicsLeft = conicCount;
GrDrawTarget::DrawInfo info;
info.setVertexBuffer(vertexBuffer);
info.setIndexBuffer(quadsIndexBuffer);
info.setPrimitiveType(kTriangles_GrPrimitiveType);
info.setStartIndex(0);
int conics = 0;
while (conics < conicCount) {
int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer);
info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVertex);
info.setVertexCount(kQuadNumVertices*n);
info.setIndexCount(kIdxsPerQuad*n);
info.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
firstVertex, kQuadNumVertices, kIdxsPerQuad, &conicsLeft,
kQuadsNumInIdxBuffer);
do {
batchTarget->draw(info);
conics += n;
}
} while (info.nextInstances(&conicsLeft, kQuadsNumInIdxBuffer));
}
}
}

View File

@ -112,22 +112,17 @@ public:
init.fUsesLocalCoords = this->usesLocalCoords();
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer(
batchTarget->resourceProvider()));
size_t vertexStride = gp->getVertexStride();
SkASSERT(canTweakAlphaForCoverage ?
vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
int instanceCount = fGeoData.count();
int vertexCount = kVertsPerAAFillRect * instanceCount;
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer(
batchTarget->resourceProvider()));
InstancedHelper helper;
void* vertices = helper.init(batchTarget, vertexStride, indexBuffer, kVertsPerAAFillRect,
kIndicesPerAAFillRect, instanceCount);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
@ -145,28 +140,7 @@ public:
canTweakAlphaForCoverage);
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerAAFillRect);
drawInfo.setIndicesPerInstance(kIndicesPerAAFillRect);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = kNumAAFillRectsInIndexBuffer;
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -485,9 +459,6 @@ public:
batchTarget->initDraw(gp, pipeline);
const SkAutoTUnref<const GrIndexBuffer> indexBuffer(
GetIndexBuffer(batchTarget->resourceProvider(), this->miterStroke()));
// TODO this is hacky, but the only way we have to initialize the GP is to use the
// GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch
// everywhere we can remove this nastiness
@ -505,28 +476,24 @@ public:
vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
int innerVertexNum = 4;
int outerVertexNum = this->miterStroke() ? 4 : 8;
int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
int verticesPerInstance = (outerVertexNum + innerVertexNum) * 2;
int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt;
int instanceCount = fGeoData.count();
int vertexCount = totalVertexNum * instanceCount;
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
const SkAutoTUnref<const GrIndexBuffer> indexBuffer(
GetIndexBuffer(batchTarget->resourceProvider(), this->miterStroke()));
InstancedHelper helper;
void* vertices = helper.init(batchTarget, vertexStride, indexBuffer, verticesPerInstance,
indicesPerInstance, instanceCount);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
SkDebugf("Could not allocate vertices\n");
return;
}
for (int i = 0; i < instanceCount; i++) {
const Geometry& args = fGeoData[i];
this->generateAAStrokeRectGeometry(vertices,
i * totalVertexNum * vertexStride,
i * verticesPerInstance * vertexStride,
vertexStride,
outerVertexNum,
innerVertexNum,
@ -537,30 +504,7 @@ public:
args.fMiterStroke,
canTweakAlphaForCoverage);
}
int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt;
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(totalVertexNum);
drawInfo.setIndicesPerInstance(indicesPerInstance);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = this->miterStroke() ? kNumMiterRectsInIndexBuffer :
kNumBevelRectsInIndexBuffer;
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }

View File

@ -1474,6 +1474,13 @@ public:
fBatch.fCoverageIgnored = init.fCoverageIgnored;
}
struct FlushInfo {
SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
int fGlyphsToFlush;
int fVertexOffset;
};
void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
// if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
// TODO actually only invert if we don't have RGBA
@ -1506,6 +1513,8 @@ public:
localMatrix));
}
FlushInfo flushInfo;
flushInfo.fGlyphsToFlush = 0;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == (fUseDistanceFields ?
get_vertex_stride_df(fMaskFormat, fUseLCDText) :
@ -1515,35 +1524,21 @@ public:
int glyphCount = this->numGlyphs();
int instanceCount = fInstanceCount;
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
glyphCount * kVerticesPerGlyph,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
&flushInfo.fVertexOffset);
flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
flushInfo.fIndexBuffer.reset(batchTarget->resourceProvider()->refQuadIndexBuffer());
if (!vertices || !flushInfo.fVertexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices);
// setup drawinfo
int maxInstancesPerDraw = indexBuffer->maxQuads();
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVerticesPerGlyph);
drawInfo.setIndicesPerInstance(kIndicesPerGlyph);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
// We cache some values to avoid going to the glyphcache for the same fontScaler twice
// in a row
const SkDescriptor* desc = NULL;
@ -1551,7 +1546,6 @@ public:
GrFontScaler* scaler = NULL;
SkTypeface* typeface = NULL;
int instancesToFlush = 0;
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
Blob* blob = args.fBlob;
@ -1635,10 +1629,8 @@ public:
if (!fFontCache->hasGlyph(glyph) &&
!strike->addGlyphToAtlas(batchTarget, glyph, scaler)) {
this->flush(batchTarget, &drawInfo, instancesToFlush,
maxInstancesPerDraw);
this->flush(batchTarget, &flushInfo);
this->initDraw(batchTarget, gp, pipeline);
instancesToFlush = 0;
brokenRun = glyphIdx > 0;
SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(batchTarget,
@ -1674,7 +1666,7 @@ public:
SkScalar transY = args.fTransY;
this->regeneratePositions(vertex, vertexStride, transX, transY);
}
instancesToFlush++;
flushInfo.fGlyphsToFlush++;
}
// We my have changed the color so update it here
@ -1687,7 +1679,7 @@ public:
fFontCache->atlasGeneration(fMaskFormat);
}
} else {
instancesToFlush += glyphCount;
flushInfo.fGlyphsToFlush += glyphCount;
// set use tokens for all of the glyphs in our subrun. This is only valid if we
// have a valid atlas generation
@ -1706,7 +1698,7 @@ public:
if (cache) {
SkGlyphCache::AttachCache(cache);
}
this->flush(batchTarget, &drawInfo, instancesToFlush, maxInstancesPerDraw);
this->flush(batchTarget, &flushInfo);
}
// The minimum number of Geometry we will try to allocate.
@ -1833,20 +1825,19 @@ private:
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
}
void flush(GrBatchTarget* batchTarget,
GrDrawTarget::DrawInfo* drawInfo,
int instanceCount,
int maxInstancesPerDraw) {
while (instanceCount) {
drawInfo->setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo->setVertexCount(drawInfo->instanceCount() * drawInfo->verticesPerInstance());
drawInfo->setIndexCount(drawInfo->instanceCount() * drawInfo->indicesPerInstance());
batchTarget->draw(*drawInfo);
drawInfo->setStartVertex(drawInfo->startVertex() + drawInfo->vertexCount());
instanceCount -= drawInfo->instanceCount();
}
void flush(GrBatchTarget* batchTarget, FlushInfo* flushInfo) {
GrDrawTarget::DrawInfo drawInfo;
int glyphsToFlush = flushInfo->fGlyphsToFlush;
int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads();
drawInfo.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
flushInfo->fIndexBuffer, flushInfo->fVertexOffset,
kVerticesPerGlyph, kIndicesPerGlyph, &glyphsToFlush,
maxGlyphsPerDraw);
do {
batchTarget->draw(drawInfo);
} while (drawInfo.nextInstances(&glyphsToFlush, maxGlyphsPerDraw));
flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;
flushInfo->fGlyphsToFlush = 0;
}
GrColor color() const { return fBatch.fColor; }

View File

@ -6,6 +6,8 @@
*/
#include "GrBatch.h"
#include "GrBatchTarget.h"
#include "GrResourceProvider.h"
#include "GrMemoryPool.h"
#include "SkSpinlock.h"
@ -43,3 +45,43 @@ void* GrBatch::operator new(size_t size) {
void GrBatch::operator delete(void* target) {
return MemoryPoolAccessor().pool()->release(target);
}
void* GrBatch::InstancedHelper::init(GrBatchTarget* batchTarget, size_t vertexStride,
const GrIndexBuffer* indexBuffer, int verticesPerInstance,
int indicesPerInstance, int instancesToDraw) {
SkASSERT(!fInstancesRemaining);
SkASSERT(batchTarget);
if (!indexBuffer) {
return NULL;
}
const GrVertexBuffer* vertexBuffer;
int firstVertex;
int vertexCount = verticesPerInstance * instancesToDraw;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, vertexCount, &vertexBuffer,
&firstVertex);
if (!vertices) {
SkDebugf("Vertices could not be allocated for instanced rendering.");
return NULL;
}
SkASSERT(vertexBuffer);
fInstancesRemaining = instancesToDraw;
fDrawInfo.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
firstVertex, verticesPerInstance, indicesPerInstance, &fInstancesRemaining,
indexBuffer->maxQuads());
size_t ibSize = fDrawInfo.indexBuffer()->gpuMemorySize();
fMaxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));
SkASSERT(fMaxInstancesPerDraw > 0);
return vertices;
}
void* GrBatch::QuadHelper::init(GrBatchTarget* batchTarget, size_t vertexStride, int quadsToDraw) {
SkAutoTUnref<const GrIndexBuffer> quadIndexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
if (!quadIndexBuffer) {
SkDebugf("Could not get quad index buffer.");
return NULL;
}
return this->INHERITED::init(batchTarget, vertexStride, quadIndexBuffer, kVerticesPerQuad,
kIndicesPerQuad, quadsToDraw);
}

View File

@ -11,12 +11,12 @@
#include <new>
// TODO remove this header when we move entirely to batch
#include "GrDrawTarget.h"
#include "GrBatchTarget.h"
#include "GrGeometryProcessor.h"
#include "SkRefCnt.h"
#include "SkThread.h"
#include "SkTypes.h"
class GrBatchTarget;
class GrGpu;
class GrIndexBufferAllocPool;
class GrPipeline;
@ -113,6 +113,48 @@ protected:
return fBounds.joinPossiblyEmptyRect(otherBounds);
}
/** Helper for rendering instances using an instanced index index buffer. This class creates the
space for the vertices and flushes the draws to the batch target.*/
class InstancedHelper {
public:
InstancedHelper() : fInstancesRemaining(0) {}
/** Returns the allocated storage for the vertices. The caller should populate the before
vertices before calling issueDraws(). */
void* init(GrBatchTarget* batchTarget, size_t vertexStride,
const GrIndexBuffer* indexBuffer, int verticesPerInstance,
int indicesPerInstance, int instancesToDraw);
/** Call after init() to issue draws to the batch target.*/
void issueDraws(GrBatchTarget* batchTarget) {
SkASSERT(fDrawInfo.instanceCount());
do {
batchTarget->draw(fDrawInfo);
} while (fDrawInfo.nextInstances(&fInstancesRemaining, fMaxInstancesPerDraw));
}
private:
int fInstancesRemaining;
int fMaxInstancesPerDraw;
GrDrawTarget::DrawInfo fDrawInfo;
};
static const int kVerticesPerQuad = 4;
static const int kIndicesPerQuad = 6;
/** A specialization of InstanceHelper for quad rendering. */
class QuadHelper : private InstancedHelper {
public:
QuadHelper() : INHERITED() {}
/** Finds the cached quad index buffer and reserves vertex space. Returns NULL on failure
and on sucess a pointer to the vertex data that the caller should populate before
calling issueDraws(). */
void* init(GrBatchTarget* batchTarget, size_t vertexStride, int quadsToDraw);
using InstancedHelper::issueDraws;
private:
typedef InstancedHelper INHERITED;
};
SkRect fBounds;
private:

View File

@ -502,15 +502,7 @@ public:
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(primType);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(vertexCount);
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(0);
drawInfo.setInstanceCount(0);
drawInfo.setVerticesPerInstance(0);
drawInfo.setIndicesPerInstance(0);
drawInfo.init(primType, vertexBuffer, firstVertex, vertexCount);
batchTarget->draw(drawInfo);
}
@ -829,8 +821,8 @@ public:
return;
}
const GrIndexBuffer* indexBuffer;
int firstIndex;
const GrIndexBuffer* indexBuffer = NULL;
int firstIndex = 0;
void* indices = NULL;
if (this->hasIndices()) {
@ -870,17 +862,12 @@ public:
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(this->primitiveType());
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(this->vertexCount());
if (this->hasIndices()) {
drawInfo.setIndexBuffer(indexBuffer);
drawInfo.setStartIndex(firstIndex);
drawInfo.setIndexCount(this->indexCount());
drawInfo.initIndexed(this->primitiveType(), vertexBuffer, indexBuffer, firstVertex,
firstIndex, this->vertexCount(), this->indexCount());
} else {
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(0);
drawInfo.init(this->primitiveType(), vertexBuffer, firstVertex, this->vertexCount());
}
batchTarget->draw(drawInfo);
}

View File

@ -329,8 +329,8 @@ public:
return;
}
const GrIndexBuffer* indexBuffer;
int firstIndex;
const GrIndexBuffer* indexBuffer = NULL;
int firstIndex = 0;
void* indices = NULL;
if (isIndexed) {
@ -370,17 +370,11 @@ public:
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(primitiveType);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(vertexOffset);
if (isIndexed) {
drawInfo.setIndexBuffer(indexBuffer);
drawInfo.setStartIndex(firstIndex);
drawInfo.setIndexCount(indexOffset);
drawInfo.initIndexed(primitiveType, vertexBuffer, indexBuffer, firstVertex, firstIndex,
vertexOffset, indexOffset);
} else {
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(0);
drawInfo.init(primitiveType, vertexBuffer, firstVertex, vertexOffset);
}
batchTarget->draw(drawInfo);

View File

@ -37,16 +37,8 @@ GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
fVerticesPerInstance = di.fVerticesPerInstance;
fIndicesPerInstance = di.fIndicesPerInstance;
if (di.fDevBounds) {
SkASSERT(di.fDevBounds == &di.fDevBoundsStorage);
fDevBoundsStorage = di.fDevBoundsStorage;
fDevBounds = &fDevBoundsStorage;
} else {
fDevBounds = NULL;
}
this->setVertexBuffer(di.vertexBuffer());
this->setIndexBuffer(di.indexBuffer());
fVertexBuffer.reset(di.vertexBuffer());
fIndexBuffer.reset(di.indexBuffer());
return *this;
}

View File

@ -225,65 +225,132 @@ public:
virtual DrawToken getCurrentDrawToken() { return DrawToken(this, 0); }
/**
* Used to communicate draws to GPUs / subclasses
* Used to communicate draw index vertex offsets and counts toto GPUs / subclasses
*/
class DrawInfo {
public:
DrawInfo() { fDevBounds = NULL; }
DrawInfo() {}
DrawInfo(const DrawInfo& di) { (*this) = di; }
DrawInfo& operator =(const DrawInfo& di);
void init(GrPrimitiveType primType, const GrVertexBuffer* vertexBuffer, int startVertex,
int vertexCount) {
SkASSERT(vertexBuffer);
SkASSERT(vertexCount);
SkASSERT(startVertex >= 0);
fPrimitiveType = primType;
fVertexBuffer.reset(SkRef(vertexBuffer));
fIndexBuffer.reset(NULL);
fStartVertex = startVertex;
fStartIndex = 0;
fVertexCount = vertexCount;
fIndexCount = 0;
fInstanceCount = 0;
fVerticesPerInstance = 0;
fIndicesPerInstance = 0;
}
void initIndexed(GrPrimitiveType primType,
const GrVertexBuffer* vertexBuffer,
const GrIndexBuffer* indexBuffer,
int startVertex,
int startIndex,
int vertexCount,
int indexCount) {
SkASSERT(indexBuffer);
SkASSERT(vertexBuffer);
SkASSERT(indexCount);
SkASSERT(vertexCount);
SkASSERT(startIndex >= 0);
SkASSERT(startVertex >= 0);
fPrimitiveType = primType;
fVertexBuffer.reset(SkRef(vertexBuffer));
fIndexBuffer.reset(SkRef(indexBuffer));
fStartVertex = startVertex;
fStartIndex = startIndex;
fVertexCount = vertexCount;
fIndexCount = indexCount;
fInstanceCount = 0;
fVerticesPerInstance = 0;
fIndicesPerInstance = 0;
}
void initInstanced(GrPrimitiveType primType,
const GrVertexBuffer* vertexBuffer,
const GrIndexBuffer* indexBuffer,
int startVertex,
int verticesPerInstance,
int indicesPerInstance,
int instanceCount) {
SkASSERT(vertexBuffer);
SkASSERT(indexBuffer);
SkASSERT(instanceCount);
SkASSERT(verticesPerInstance);
SkASSERT(indicesPerInstance);
SkASSERT(startVertex >= 0);
fPrimitiveType = primType;
fVertexBuffer.reset(SkRef(vertexBuffer));
fIndexBuffer.reset(SkRef(indexBuffer));
fStartVertex = startVertex;
fStartIndex = 0;
fVerticesPerInstance = verticesPerInstance;
fIndicesPerInstance = indicesPerInstance;
fInstanceCount = instanceCount;
fVertexCount = instanceCount * fVerticesPerInstance;
fIndexCount = instanceCount * fIndicesPerInstance;
}
/** Variation of the above that may be used when the total number of instances may exceed
the number of instances supported by the index buffer. To be used with
nextInstances() to draw in max-sized batches.*/
void initInstanced(GrPrimitiveType primType,
const GrVertexBuffer* vertexBuffer,
const GrIndexBuffer* indexBuffer,
int startVertex,
int verticesPerInstance,
int indicesPerInstance,
int* instancesRemaining,
int maxInstancesPerDraw) {
int instanceCount = SkTMin(*instancesRemaining, maxInstancesPerDraw);
*instancesRemaining -= instanceCount;
this->initInstanced(primType, vertexBuffer, indexBuffer, startVertex,
verticesPerInstance, indicesPerInstance, instanceCount);
}
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
int startVertex() const { return fStartVertex; }
int startIndex() const { return fStartIndex; }
int vertexCount() const { return fVertexCount; }
int indexCount() const { return fIndexCount; }
/** These return 0 if initInstanced was not used to initialize the DrawInfo. */
int verticesPerInstance() const { return fVerticesPerInstance; }
int indicesPerInstance() const { return fIndicesPerInstance; }
int instanceCount() const { return fInstanceCount; }
void setPrimitiveType(GrPrimitiveType type) { fPrimitiveType = type; }
void setStartVertex(int startVertex) { fStartVertex = startVertex; }
void setStartIndex(int startIndex) { fStartIndex = startIndex; }
void setVertexCount(int vertexCount) { fVertexCount = vertexCount; }
void setIndexCount(int indexCount) { fIndexCount = indexCount; }
void setVerticesPerInstance(int verticesPerI) { fVerticesPerInstance = verticesPerI; }
void setIndicesPerInstance(int indicesPerI) { fIndicesPerInstance = indicesPerI; }
void setInstanceCount(int instanceCount) { fInstanceCount = instanceCount; }
bool isIndexed() const { return fIndexCount > 0; }
#ifdef SK_DEBUG
bool isInstanced() const; // this version is longer because of asserts
#else
bool isInstanced() const { return fInstanceCount > 0; }
#endif
// adds or remove instances
void adjustInstanceCount(int instanceOffset);
// shifts the start vertex
void adjustStartVertex(int vertexOffset) {
fStartVertex += vertexOffset;
SkASSERT(fStartVertex >= 0);
}
// shifts the start index
void adjustStartIndex(int indexOffset) {
SkASSERT(this->isIndexed());
fStartIndex += indexOffset;
SkASSERT(fStartIndex >= 0);
}
void setDevBounds(const SkRect& bounds) {
fDevBoundsStorage = bounds;
fDevBounds = &fDevBoundsStorage;
/** Called after using this draw info to draw the next set of instances.
The vertex offset is advanced while the index buffer is reused at the same
position. instancesRemaining is number of instances that remain, maxInstances is
the most number of instances that can be used with the index buffer. If there
are no instances remaining, the DrawInfo is unmodified and false is returned.*/
bool nextInstances(int* instancesRemaining, int maxInstances) {
SkASSERT(this->isInstanced());
if (!*instancesRemaining) {
return false;
}
fStartVertex += fVertexCount;
fInstanceCount = SkTMin(*instancesRemaining, maxInstances);
fVertexCount = fInstanceCount * fVerticesPerInstance;
fIndexCount = fInstanceCount * fIndicesPerInstance;
*instancesRemaining -= fInstanceCount;
return true;
}
const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); }
void setVertexBuffer(const GrVertexBuffer* vb) {
fVertexBuffer.reset(vb);
}
void setIndexBuffer(const GrIndexBuffer* ib) {
fIndexBuffer.reset(ib);
}
const SkRect* getDevBounds() const { return fDevBounds; }
private:
friend class GrDrawTarget;
@ -299,9 +366,6 @@ public:
int fVerticesPerInstance;
int fIndicesPerInstance;
SkRect fDevBoundsStorage;
SkRect* fDevBounds;
GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType> fVertexBuffer;
GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType> fIndexBuffer;
};

View File

@ -8,7 +8,6 @@
#include "GrInOrderDrawBuffer.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrResourceProvider.h"
#include "GrTemplates.h"
GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context,
@ -132,79 +131,49 @@ public:
init.fUsesLocalCoords = this->usesLocalCoords();
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
int instanceCount = fGeoData.count();
size_t vertexStride = gp->getVertexStride();
SkASSERT(hasExplicitLocalCoords ?
vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
QuadHelper helper;
void* vertices = helper.init(batchTarget, vertexStride, instanceCount);
int instanceCount = fGeoData.count();
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
int vertexCount = kVertsPerRect * instanceCount;
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
if (!vertices) {
return;
}
for (int i = 0; i < instanceCount; i++) {
const Geometry& args = fGeoData[i];
intptr_t offset = GrTCast<intptr_t>(vertices) + kVertsPerRect * i * vertexStride;
for (int i = 0; i < instanceCount; i++) {
const Geometry& geom = fGeoData[i];
intptr_t offset = GrTCast<intptr_t>(vertices) + kVerticesPerQuad * i * vertexStride;
SkPoint* positions = GrTCast<SkPoint*>(offset);
positions->setRectFan(args.fRect.fLeft, args.fRect.fTop,
args.fRect.fRight, args.fRect.fBottom, vertexStride);
args.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerRect);
positions->setRectFan(geom.fRect.fLeft, geom.fRect.fTop,
geom.fRect.fRight, geom.fRect.fBottom, vertexStride);
geom.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerticesPerQuad);
if (args.fHasLocalRect) {
if (geom.fHasLocalRect) {
static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
SkPoint* coords = GrTCast<SkPoint*>(offset + kLocalOffset);
coords->setRectFan(args.fLocalRect.fLeft, args.fLocalRect.fTop,
args.fLocalRect.fRight, args.fLocalRect.fBottom,
coords->setRectFan(geom.fLocalRect.fLeft, geom.fLocalRect.fTop,
geom.fLocalRect.fRight, geom.fLocalRect.fBottom,
vertexStride);
if (args.fHasLocalMatrix) {
args.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVertsPerRect);
if (geom.fHasLocalMatrix) {
geom.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVerticesPerQuad);
}
}
static const int kColorOffset = sizeof(SkPoint);
GrColor* vertColor = GrTCast<GrColor*>(offset + kColorOffset);
for (int j = 0; j < 4; ++j) {
*vertColor = args.fColor;
*vertColor = geom.fColor;
vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
}
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerRect);
drawInfo.setIndicesPerInstance(kIndicesPerRect);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = indexBuffer->maxQuads();
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -263,9 +232,6 @@ private:
bool fCoverageIgnored;
};
const static int kVertsPerRect = 4;
const static int kIndicesPerRect = 6;
BatchTracker fBatch;
SkSTArray<1, Geometry, true> fGeoData;
};

View File

@ -744,34 +744,22 @@ public:
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
int instanceCount = fGeoData.count();
int vertexCount = kVertsPerCircle * instanceCount;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(CircleVertex));
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
QuadHelper helper;
CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(batchTarget, vertexStride,
instanceCount));
if (!verts) {
return;
}
CircleVertex* verts = reinterpret_cast<CircleVertex*>(vertices);
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
Geometry& geom = fGeoData[i];
SkScalar innerRadius = args.fInnerRadius;
SkScalar outerRadius = args.fOuterRadius;
SkScalar innerRadius = geom.fInnerRadius;
SkScalar outerRadius = geom.fOuterRadius;
const SkRect& bounds = args.fDevBounds;
const SkRect& bounds = geom.fDevBounds;
// The inner radius in the vertex data must be specified in normalized space.
innerRadius = innerRadius / outerRadius;
@ -795,31 +783,9 @@ public:
verts[3].fOuterRadius = outerRadius;
verts[3].fInnerRadius = innerRadius;
verts += kVertsPerCircle;
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerCircle);
drawInfo.setIndicesPerInstance(kIndicesPerCircle);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = indexBuffer->maxQuads();
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
verts += kVerticesPerQuad;
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -867,9 +833,6 @@ private:
bool fCoverageIgnored;
};
static const int kVertsPerCircle = 4;
static const int kIndicesPerCircle = 6;
BatchTracker fBatch;
SkSTArray<1, Geometry, true> fGeoData;
};
@ -1009,40 +972,28 @@ public:
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
int instanceCount = fGeoData.count();
int vertexCount = kVertsPerEllipse * instanceCount;
QuadHelper helper;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(EllipseVertex));
const GrVertexBuffer* vertexBuffer;
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
int firstVertex;
void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
helper.init(batchTarget, vertexStride, instanceCount));
if (!verts) {
return;
}
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(vertices);
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
Geometry& geom = fGeoData[i];
SkScalar xRadius = args.fXRadius;
SkScalar yRadius = args.fYRadius;
SkScalar xRadius = geom.fXRadius;
SkScalar yRadius = geom.fYRadius;
// Compute the reciprocals of the radii here to save time in the shader
SkScalar xRadRecip = SkScalarInvert(xRadius);
SkScalar yRadRecip = SkScalarInvert(yRadius);
SkScalar xInnerRadRecip = SkScalarInvert(args.fInnerXRadius);
SkScalar yInnerRadRecip = SkScalarInvert(args.fInnerYRadius);
SkScalar xInnerRadRecip = SkScalarInvert(geom.fInnerXRadius);
SkScalar yInnerRadRecip = SkScalarInvert(geom.fInnerYRadius);
const SkRect& bounds = args.fDevBounds;
const SkRect& bounds = geom.fDevBounds;
// The inner radius in the vertex data must be specified in normalized space.
verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
@ -1065,31 +1016,9 @@ public:
verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
verts += kVertsPerEllipse;
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerEllipse);
drawInfo.setIndicesPerInstance(kIndicesPerEllipse);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = indexBuffer->maxQuads();
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
verts += kVerticesPerQuad;
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -1137,9 +1066,6 @@ private:
bool fCoverageIgnored;
};
static const int kVertsPerEllipse = 4;
static const int kIndicesPerEllipse = 6;
BatchTracker fBatch;
SkSTArray<1, Geometry, true> fGeoData;
};
@ -1317,41 +1243,30 @@ public:
init.fUsesLocalCoords = this->usesLocalCoords();
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
int instanceCount = fGeoData.count();
int vertexCount = kVertsPerEllipse * instanceCount;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(DIEllipseVertex));
const GrVertexBuffer* vertexBuffer;
int firstVertex;
void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
QuadHelper helper;
DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(
helper.init(batchTarget, vertexStride, instanceCount));
if (!verts) {
return;
}
DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(vertices);
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
Geometry& geom = fGeoData[i];
SkScalar xRadius = args.fXRadius;
SkScalar yRadius = args.fYRadius;
SkScalar xRadius = geom.fXRadius;
SkScalar yRadius = geom.fYRadius;
const SkRect& bounds = args.fBounds;
const SkRect& bounds = geom.fBounds;
// This adjusts the "radius" to include the half-pixel border
SkScalar offsetDx = SkScalarDiv(args.fGeoDx, xRadius);
SkScalar offsetDy = SkScalarDiv(args.fGeoDy, yRadius);
SkScalar offsetDx = SkScalarDiv(geom.fGeoDx, xRadius);
SkScalar offsetDy = SkScalarDiv(geom.fGeoDy, yRadius);
SkScalar innerRatioX = SkScalarDiv(xRadius, args.fInnerXRadius);
SkScalar innerRatioY = SkScalarDiv(yRadius, args.fInnerYRadius);
SkScalar innerRatioX = SkScalarDiv(xRadius, geom.fInnerXRadius);
SkScalar innerRatioY = SkScalarDiv(yRadius, geom.fInnerYRadius);
verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
verts[0].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy);
@ -1369,31 +1284,9 @@ public:
verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy);
verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy);
verts += kVertsPerEllipse;
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerEllipse);
drawInfo.setIndicesPerInstance(kIndicesPerEllipse);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = indexBuffer->maxQuads();
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
verts += kVerticesPerQuad;
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -1441,9 +1334,6 @@ private:
bool fCoverageIgnored;
};
static const int kVertsPerEllipse = 4;
static const int kIndicesPerEllipse = 6;
BatchTracker fBatch;
SkSTArray<1, Geometry, true> fGeoData;
};
@ -1722,27 +1612,22 @@ public:
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
int instanceCount = fGeoData.count();
int vertexCount = kVertsPerRRect * instanceCount;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(CircleVertex));
const GrVertexBuffer* vertexBuffer;
// drop out the middle quad if we're stroked
int indicesPerInstance = this->stroke() ? kIndicesPerStrokeRRect : kIndicesPerRRect;
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
ref_rrect_index_buffer(this->stroke(), batchTarget->resourceProvider()));
int firstVertex;
void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
InstancedHelper helper;
CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(batchTarget,
vertexStride, indexBuffer, kVertsPerRRect, indicesPerInstance, instanceCount));
if (!verts || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
CircleVertex* verts = reinterpret_cast<CircleVertex*>(vertices);
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
@ -1787,32 +1672,7 @@ public:
}
}
// drop out the middle quad if we're stroked
int indexCnt = this->stroke() ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
SK_ARRAY_COUNT(gRRectIndices);
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerRRect);
drawInfo.setIndicesPerInstance(indexCnt);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = kNumRRectsInIndexBuffer;
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
@ -1933,27 +1793,23 @@ public:
gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
int instanceCount = fGeoData.count();
int vertexCount = kVertsPerRRect * instanceCount;
size_t vertexStride = gp->getVertexStride();
SkASSERT(vertexStride == sizeof(EllipseVertex));
const GrVertexBuffer* vertexBuffer;
// drop out the middle quad if we're stroked
int indicesPerInstance = this->stroke() ? kIndicesPerStrokeRRect : kIndicesPerRRect;
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
ref_rrect_index_buffer(this->stroke(), batchTarget->resourceProvider()));
int firstVertex;
void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
vertexCount,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
InstancedHelper helper;
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
helper.init(batchTarget, vertexStride, indexBuffer, kVertsPerRRect, indicesPerInstance,
instanceCount));
if (!verts || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(vertices);
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
@ -2008,33 +1864,7 @@ public:
verts++;
}
}
// drop out the middle quad if we're stroked
int indexCnt = this->stroke() ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
SK_ARRAY_COUNT(gRRectIndices);
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerRRect);
drawInfo.setIndicesPerInstance(indexCnt);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = kNumRRectsInIndexBuffer;
while (instanceCount) {
drawInfo.setInstanceCount(SkTMin(instanceCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
instanceCount -= drawInfo.instanceCount();
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }

View File

@ -1459,12 +1459,7 @@ public:
GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
: kTriangles_GrPrimitiveType;
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(primitiveType);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setStartVertex(firstVertex);
drawInfo.setVertexCount(actualCount);
drawInfo.setStartIndex(0);
drawInfo.setIndexCount(0);
drawInfo.init(primitiveType, vertexBuffer, firstVertex, actualCount);
batchTarget->draw(drawInfo);
batchTarget->putBackVertices((size_t)(count - actualCount), stride);

View File

@ -19,7 +19,6 @@
#include "GrDrawTargetCaps.h"
#include "GrInvariantOutput.h"
#include "GrProcessor.h"
#include "GrResourceProvider.h"
#include "GrStrokeInfo.h"
#include "GrVertexBuffer.h"
#include "SkGr.h"
@ -536,38 +535,29 @@ public:
draw.fHasEndRect = hasEndRect;
}
SkAutoTUnref<const GrIndexBuffer> indexBuffer(
batchTarget->resourceProvider()->refQuadIndexBuffer());
const GrVertexBuffer* vertexBuffer;
int firstVertex;
size_t vertexStride = gp->getVertexStride();
void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
totalRectCount * kVertsPerDash,
&vertexBuffer,
&firstVertex);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate buffers\n");
QuadHelper helper;
void* vertices = helper.init(batchTarget, gp->getVertexStride(), instanceCount);
if (!vertices) {
return;
}
int curVIdx = 0;
int rectIndex = 0;
for (int i = 0; i < instanceCount; i++) {
Geometry& args = fGeoData[i];
Geometry& geom = fGeoData[i];
if (!draws[i].fLineDone) {
if (fullDash) {
setup_dashed_rect(rects[rectIndex], vertices, curVIdx, args.fSrcRotInv,
setup_dashed_rect(rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX,
draws[i].fDevBloatY, draws[i].fLineLength,
draws[i].fHalfDevStroke, args.fIntervals[0],
args.fIntervals[1], draws[i].fStrokeWidth,
draws[i].fHalfDevStroke, geom.fIntervals[0],
geom.fIntervals[1], draws[i].fStrokeWidth,
capType, gp->getVertexStride());
} else {
SkPoint* verts = reinterpret_cast<SkPoint*>(vertices);
SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
setup_dashed_rect_pos(rects[rectIndex], curVIdx, args.fSrcRotInv, verts);
setup_dashed_rect_pos(rects[rectIndex], curVIdx, geom.fSrcRotInv, verts);
}
curVIdx += 4;
}
@ -575,16 +565,16 @@ public:
if (draws[i].fHasStartRect) {
if (fullDash) {
setup_dashed_rect(rects[rectIndex], vertices, curVIdx, args.fSrcRotInv,
setup_dashed_rect(rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX,
draws[i].fDevBloatY, args.fIntervals[0],
draws[i].fHalfDevStroke, args.fIntervals[0],
args.fIntervals[1], draws[i].fStrokeWidth, capType,
draws[i].fDevBloatY, geom.fIntervals[0],
draws[i].fHalfDevStroke, geom.fIntervals[0],
geom.fIntervals[1], draws[i].fStrokeWidth, capType,
gp->getVertexStride());
} else {
SkPoint* verts = reinterpret_cast<SkPoint*>(vertices);
SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
setup_dashed_rect_pos(rects[rectIndex], curVIdx, args.fSrcRotInv, verts);
setup_dashed_rect_pos(rects[rectIndex], curVIdx, geom.fSrcRotInv, verts);
}
curVIdx += 4;
@ -593,43 +583,22 @@ public:
if (draws[i].fHasEndRect) {
if (fullDash) {
setup_dashed_rect(rects[rectIndex], vertices, curVIdx, args.fSrcRotInv,
setup_dashed_rect(rects[rectIndex], vertices, curVIdx, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX,
draws[i].fDevBloatY, args.fIntervals[0],
draws[i].fHalfDevStroke, args.fIntervals[0],
args.fIntervals[1], draws[i].fStrokeWidth, capType,
draws[i].fDevBloatY, geom.fIntervals[0],
draws[i].fHalfDevStroke, geom.fIntervals[0],
geom.fIntervals[1], draws[i].fStrokeWidth, capType,
gp->getVertexStride());
} else {
SkPoint* verts = reinterpret_cast<SkPoint*>(vertices);
SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
setup_dashed_rect_pos(rects[rectIndex], curVIdx, args.fSrcRotInv, verts);
setup_dashed_rect_pos(rects[rectIndex], curVIdx, geom.fSrcRotInv, verts);
}
curVIdx += 4;
}
rectIndex++;
}
GrDrawTarget::DrawInfo drawInfo;
drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
drawInfo.setStartVertex(0);
drawInfo.setStartIndex(0);
drawInfo.setVerticesPerInstance(kVertsPerDash);
drawInfo.setIndicesPerInstance(kIndicesPerDash);
drawInfo.adjustStartVertex(firstVertex);
drawInfo.setVertexBuffer(vertexBuffer);
drawInfo.setIndexBuffer(indexBuffer);
int maxInstancesPerDraw = indexBuffer->maxQuads();
while (totalRectCount) {
drawInfo.setInstanceCount(SkTMin(totalRectCount, maxInstancesPerDraw));
drawInfo.setVertexCount(drawInfo.instanceCount() * drawInfo.verticesPerInstance());
drawInfo.setIndexCount(drawInfo.instanceCount() * drawInfo.indicesPerInstance());
batchTarget->draw(drawInfo);
drawInfo.setStartVertex(drawInfo.startVertex() + drawInfo.vertexCount());
totalRectCount -= drawInfo.instanceCount();
}
helper.issueDraws(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }