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);
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
Geometry fGeometry;
fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
sizeof(Vertex));
fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
Geometry fGeometry;
fGeometry.fBounds.outset(5.f, 5.f);
fGeometry.fBounds.toQuad(verts);
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
Geometry fGeometry;
int firstVertex;
size_t vertexStride = quadProcessor->getVertexStride();
- void *vertices = batchTarget->makeVertSpace(vertexStride, vertexCount,
- &vertexBuffer, &firstVertex);
- if (!vertices) {
+ QuadVertex* verts = reinterpret_cast<QuadVertex*>(batchTarget->makeVertSpace(
+ vertexStride, vertexCount, &vertexBuffer, &firstVertex));
+
+ if (!verts) {
SkDebugf("Could not allocate vertices\n");
return;
}
return;
}
- QuadVertex* verts = reinterpret_cast<QuadVertex*>(vertices);
-
SkSTArray<kPreallocDrawCnt, Draw, true> draws;
create_vertices(segments, fanPt, &draws, verts, idxs);
- GrVertices info;
+ GrVertices vertices;
for (int i = 0; i < draws.count(); ++i) {
const Draw& draw = draws[i];
- info.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex,
- firstIndex, draw.fVertexCnt, draw.fIndexCnt);
- batchTarget->draw(info);
+ vertices.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
+ firstVertex, firstIndex, draw.fVertexCnt, draw.fIndexCnt);
+ batchTarget->draw(vertices);
firstVertex += draw.fVertexCnt;
firstIndex += draw.fIndexCnt;
}
void flush(GrBatchTarget* batchTarget, FlushInfo* flushInfo) {
GrVertices vertices;
- int instancesToFlush = flushInfo->fInstancesToFlush;
int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads();
vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad,
- kIndicesPerQuad, &instancesToFlush, maxInstancesPerDraw);
- do {
- batchTarget->draw(vertices);
- } while (vertices.nextInstances(&instancesToFlush, maxInstancesPerDraw));
+ kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw);
+ batchTarget->draw(vertices);
flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFlush;
flushInfo->fInstancesToFlush = 0;
}
size_t vertexStride = lineGP->getVertexStride();
int vertexCount = kLineSegNumVertices * lineCount;
- void *vertices = batchTarget->makeVertSpace(vertexStride, vertexCount,
- &vertexBuffer, &firstVertex);
+ LineVertex* verts = reinterpret_cast<LineVertex*>(
+ batchTarget->makeVertSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex));
- if (!vertices || !linesIndexBuffer) {
+ if (!verts|| !linesIndexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex));
- LineVertex* verts = reinterpret_cast<LineVertex*>(vertices);
for (int i = 0; i < lineCount; ++i) {
add_line(&lines[2*i], toSrc, this->coverage(), &verts);
}
{
- int linesLeft = lineCount;
- GrVertices info;
- info.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, linesIndexBuffer,
- firstVertex, kLineSegNumVertices, kIdxsPerLineSeg, &linesLeft,
- kLineSegsNumInIdxBuffer);
- do {
- batchTarget->draw(info);
- } while (info.nextInstances(&linesLeft, kLineSegsNumInIdxBuffer));
+ GrVertices vertices;
+ vertices.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, linesIndexBuffer,
+ firstVertex, kLineSegNumVertices, kIdxsPerLineSeg, lineCount,
+ kLineSegsNumInIdxBuffer);
+ batchTarget->draw(vertices);
}
}
quadGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
{
- int quadsLeft = quadCount;
- GrVertices info;
- info.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
- firstVertex, kQuadNumVertices, kIdxsPerQuad, &quadsLeft,
- kQuadsNumInIdxBuffer);
- do {
- batchTarget->draw(info);
- } while (info.nextInstances(&quadsLeft, kQuadsNumInIdxBuffer));
- firstVertex += quadCount * kQuadNumVertices;
+ GrVertices verts;
+ verts.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
+ firstVertex, kQuadNumVertices, kIdxsPerQuad, quadCount,
+ kQuadsNumInIdxBuffer);
+ batchTarget->draw(verts);
+ firstVertex += quadCount * kQuadNumVertices;
}
}
conicGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
{
- int conicsLeft = conicCount;
- GrVertices info;
- info.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
- firstVertex, kQuadNumVertices, kIdxsPerQuad, &conicsLeft,
- kQuadsNumInIdxBuffer);
- do {
- batchTarget->draw(info);
- } while (info.nextInstances(&conicsLeft, kQuadsNumInIdxBuffer));
+ GrVertices verts;
+ verts.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer,
+ firstVertex, kQuadNumVertices, kIdxsPerQuad, conicCount,
+ kQuadsNumInIdxBuffer);
+ batchTarget->draw(verts);
}
}
}
canTweakAlphaForCoverage);
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
args.fMiterStroke,
canTweakAlphaForCoverage);
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
void flush(GrBatchTarget* batchTarget, FlushInfo* flushInfo) {
GrVertices vertices;
- int glyphsToFlush = flushInfo->fGlyphsToFlush;
int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads();
vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
flushInfo->fIndexBuffer, flushInfo->fVertexOffset,
- kVerticesPerGlyph, kIndicesPerGlyph, &glyphsToFlush,
+ kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->fGlyphsToFlush,
maxGlyphsPerDraw);
- do {
- batchTarget->draw(vertices);
- } while (vertices.nextInstances(&glyphsToFlush, maxGlyphsPerDraw));
+ batchTarget->draw(vertices);
flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;
flushInfo->fGlyphsToFlush = 0;
}
size_t vertexStride, const GrIndexBuffer* indexBuffer,
int verticesPerInstance, int indicesPerInstance,
int instancesToDraw) {
- SkASSERT(!fInstancesRemaining);
SkASSERT(batchTarget);
if (!indexBuffer) {
return NULL;
return NULL;
}
SkASSERT(vertexBuffer);
- fInstancesRemaining = instancesToDraw;
size_t ibSize = indexBuffer->gpuMemorySize();
- fMaxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));
+ int maxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));
fVertices.initInstanced(primType, vertexBuffer, indexBuffer,
- firstVertex, verticesPerInstance, indicesPerInstance, &fInstancesRemaining,
- fMaxInstancesPerDraw);
- SkASSERT(fMaxInstancesPerDraw > 0);
+ firstVertex, verticesPerInstance, indicesPerInstance, instancesToDraw,
+ maxInstancesPerDraw);
return vertices;
}
space for the vertices and flushes the draws to the batch target.*/
class InstancedHelper {
public:
- InstancedHelper() : fInstancesRemaining(0) {}
+ InstancedHelper() {}
/** Returns the allocated storage for the vertices. The caller should populate the before
vertices before calling issueDraws(). */
void* init(GrBatchTarget* batchTarget, GrPrimitiveType, size_t vertexStride,
int instancesToDraw);
/** Call after init() to issue draws to the batch target.*/
- void issueDraws(GrBatchTarget* batchTarget) {
+ void issueDraw(GrBatchTarget* batchTarget) {
SkASSERT(fVertices.instanceCount());
- do {
- batchTarget->draw(fVertices);
- } while (fVertices.nextInstances(&fInstancesRemaining, fMaxInstancesPerDraw));
+ batchTarget->draw(fVertices);
}
private:
- int fInstancesRemaining;
- int fMaxInstancesPerDraw;
GrVertices fVertices;
};
calling issueDraws(). */
void* init(GrBatchTarget* batchTarget, size_t vertexStride, int quadsToDraw);
- using InstancedHelper::issueDraws;
+ using InstancedHelper::issueDraw;
private:
typedef InstancedHelper INHERITED;
fInstanceCount = di.fInstanceCount;
fVerticesPerInstance = di.fVerticesPerInstance;
fIndicesPerInstance = di.fIndicesPerInstance;
+ fMaxInstancesPerDraw = di.fMaxInstancesPerDraw;
fVertexBuffer.reset(di.vertexBuffer());
fIndexBuffer.reset(di.indexBuffer());
void GrGpu::draw(const DrawArgs& args, const GrVertices& vertices) {
this->handleDirtyContext();
- this->onDraw(args, vertices);
+ GrVertices::Iterator iter;
+ const GrNonInstancedVertices* verts = iter.init(vertices);
+ do {
+ this->onDraw(args, *verts);
+ } while ((verts = iter.next()));
}
void GrGpu::stencilPath(const GrPath* path, const StencilPathState& state) {
#include "SkPath.h"
class GrContext;
+class GrNonInstancedVertices;
class GrPath;
class GrPathRange;
class GrPathRenderer;
virtual void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) = 0;
// overridden by backend-specific derived class to perform the draw call.
- virtual void onDraw(const DrawArgs&, const GrVertices&) = 0;
+ virtual void onDraw(const DrawArgs&, const GrNonInstancedVertices&) = 0;
virtual void onStencilPath(const GrPath*, const StencilPathState&) = 0;
virtual void onDrawPath(const DrawArgs&, const GrPath*, const GrStencilSettings&) = 0;
verts += kVerticesPerQuad;
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
verts += kVerticesPerQuad;
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
verts += kVerticesPerQuad;
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
}
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
verts++;
}
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
}
}
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override {}
- void onDraw(const DrawArgs&, const GrVertices&) override {}
+ void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override {}
void onStencilPath(const GrPath* path, const StencilPathState& state) override {}
#include "GrIndexBuffer.h"
#include "GrVertexBuffer.h"
+class GrNonInstancedVertices {
+public:
+ 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; }
+ bool isIndexed() const { return fIndexCount > 0; }
+
+ const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); }
+ const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); }
+
+protected:
+ GrPrimitiveType fPrimitiveType;
+ int fStartVertex;
+ int fStartIndex;
+ int fVertexCount;
+ int fIndexCount;
+ GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType> fVertexBuffer;
+ GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType> fIndexBuffer;
+ friend class GrVertices;
+};
+
/**
* Used to communicate index and vertex buffers, counts, and offsets for a draw from GrBatch to
* GrGpu. It also holds the primitive type for the draw. TODO: Consider moving ownership of this
* and draw-issuing responsibility to GrPrimitiveProcessor. The rest of the vertex info lives there
* already (stride, attribute mappings).
*/
-class GrVertices {
+class GrVertices : public GrNonInstancedVertices {
public:
GrVertices() {}
GrVertices(const GrVertices& di) { (*this) = di; }
fInstanceCount = 0;
fVerticesPerInstance = 0;
fIndicesPerInstance = 0;
+ fMaxInstancesPerDraw = 0;
}
void initIndexed(GrPrimitiveType primType,
fInstanceCount = 0;
fVerticesPerInstance = 0;
fIndicesPerInstance = 0;
+ fMaxInstancesPerDraw = 0;
}
+
+ /** 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 instanceCount) {
+ int instanceCount,
+ int maxInstancesPerDraw) {
SkASSERT(vertexBuffer);
SkASSERT(indexBuffer);
SkASSERT(instanceCount);
fInstanceCount = instanceCount;
fVertexCount = instanceCount * fVerticesPerInstance;
fIndexCount = instanceCount * fIndicesPerInstance;
+ fMaxInstancesPerDraw = maxInstancesPerDraw;
}
- /** 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 GrVertices. */
int verticesPerInstance() const { return fVerticesPerInstance; }
int indicesPerInstance() const { return fIndicesPerInstance; }
int instanceCount() const { return fInstanceCount; }
- bool isIndexed() const { return fIndexCount > 0; }
bool isInstanced() const { return fInstanceCount > 0; }
- /** 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 GrVertices is unmodified and false is returned.*/
- bool nextInstances(int* instancesRemaining, int maxInstances) {
- SkASSERT(this->isInstanced());
- if (!*instancesRemaining) {
- return false;
+ class Iterator {
+ public:
+ const GrNonInstancedVertices* init(const GrVertices& vertices) {
+ fVertices = &vertices;
+ if (vertices.fInstanceCount <= vertices.fMaxInstancesPerDraw) {
+ fInstancesRemaining = 0;
+ // Note, this also covers the non-instanced case!
+ return &vertices;
+ }
+ SkASSERT(vertices.isInstanced());
+ fInstanceBatch.fIndexBuffer.reset(vertices.fIndexBuffer.get());
+ fInstanceBatch.fVertexBuffer.reset(vertices.fVertexBuffer.get());
+ fInstanceBatch.fIndexCount = vertices.fMaxInstancesPerDraw *
+ vertices.fIndicesPerInstance;
+ fInstanceBatch.fVertexCount = vertices.fMaxInstancesPerDraw *
+ vertices.fVerticesPerInstance;
+ fInstanceBatch.fPrimitiveType = vertices.fPrimitiveType;
+ fInstanceBatch.fStartIndex = vertices.fStartIndex;
+ fInstanceBatch.fStartVertex = vertices.fStartVertex;
+ fInstancesRemaining = vertices.fInstanceCount - vertices.fMaxInstancesPerDraw;
+ return &fInstanceBatch;
}
- 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(); }
+ const GrNonInstancedVertices* next() {
+ if (!fInstancesRemaining) {
+ return NULL;
+ }
+ fInstanceBatch.fStartVertex += fInstanceBatch.fVertexCount;
+ int instances = SkTMin(fInstancesRemaining, fVertices->fMaxInstancesPerDraw);
+ fInstanceBatch.fIndexCount = instances * fVertices->fIndicesPerInstance;
+ fInstanceBatch.fVertexCount = instances * fVertices->fVerticesPerInstance;
+ fInstancesRemaining -= instances;
+ return &fInstanceBatch;
+ }
+ private:
+ GrNonInstancedVertices fInstanceBatch;
+ const GrVertices* fVertices;
+ int fInstancesRemaining;
+ };
private:
- GrPrimitiveType fPrimitiveType;
-
- int fStartVertex;
- int fStartIndex;
- int fVertexCount;
- int fIndexCount;
-
int fInstanceCount;
int fVerticesPerInstance;
int fIndicesPerInstance;
-
- GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType> fVertexBuffer;
- GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType> fIndexBuffer;
+ int fMaxInstancesPerDraw;
};
#endif
rectIndex++;
}
SkASSERT(0 == (curVIdx % 4) && (curVIdx / 4) == totalRectCount);
- helper.issueDraws(batchTarget);
+ helper.issueDraw(batchTarget);
}
SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
}
void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
- const GrVertices& info,
+ const GrNonInstancedVertices& vertices,
size_t* indexOffsetInBytes) {
GrGLVertexBuffer* vbuf;
- vbuf = (GrGLVertexBuffer*) info.vertexBuffer();
+ vbuf = (GrGLVertexBuffer*) vertices.vertexBuffer();
SkASSERT(vbuf);
SkASSERT(!vbuf->isMapped());
GrGLIndexBuffer* ibuf = NULL;
- if (info.isIndexed()) {
+ if (vertices.isIndexed()) {
SkASSERT(indexOffsetInBytes);
*indexOffsetInBytes = 0;
- ibuf = (GrGLIndexBuffer*)info.indexBuffer();
+ ibuf = (GrGLIndexBuffer*)vertices.indexBuffer();
SkASSERT(ibuf);
SkASSERT(!ibuf->isMapped());
GrGLsizei stride = static_cast<GrGLsizei>(primProc.getVertexStride());
- size_t vertexOffsetInBytes = stride * info.startVertex();
+ size_t vertexOffsetInBytes = stride * vertices.startVertex();
vertexOffsetInBytes += vbuf->baseOffset();
#endif
#endif
-void GrGLGpu::onDraw(const DrawArgs& args, const GrVertices& vertices) {
+void GrGLGpu::onDraw(const DrawArgs& args, const GrNonInstancedVertices& vertices) {
if (!this->flushGLState(args)) {
return;
}
#include "SkTypes.h"
class GrPipeline;
-class GrVertices;
+class GrNonInstancedVertices;
#ifdef SK_DEVELOPER
#define PROGRAM_CACHE_STATS
void onResolveRenderTarget(GrRenderTarget* target) override;
- void onDraw(const DrawArgs&, const GrVertices&) override;
+ void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override;
void onStencilPath(const GrPath*, const StencilPathState&) override;
void onDrawPath(const DrawArgs&, const GrPath*, const GrStencilSettings&) override;
void onDrawPaths(const DrawArgs&,
// an into the index buffer. It does not account for vertices.startIndex() but rather the start
// index is relative to the returned offset.
void setupGeometry(const GrPrimitiveProcessor&,
- const GrVertices& vertices,
+ const GrNonInstancedVertices& vertices,
size_t* indexOffsetInBytes);
// Subclasses should call this to flush the blend state.