Chromium Code Reviews| Index: src/gpu/GrContext.cpp |
| diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp |
| index 85ea9cab28780978486f62233ed460a5a799b2ab..1efd244b292201a2e324e0425b47125c12a3345b 100755 |
| --- a/src/gpu/GrContext.cpp |
| +++ b/src/gpu/GrContext.cpp |
| @@ -9,6 +9,8 @@ |
| #include "GrContext.h" |
| #include "GrAARectRenderer.h" |
| +#include "GrBatch.h" |
| +#include "GrBatchTarget.h" |
| #include "GrBufferAllocPool.h" |
| #include "GrDefaultGeoProcFactory.h" |
| #include "GrFontCache.h" |
| @@ -440,28 +442,6 @@ void GrContext::dumpFontCache() const { |
| //////////////////////////////////////////////////////////////////////////////// |
| -/* create a triangle strip that strokes the specified triangle. There are 8 |
| - unique vertices, but we repreat the last 2 to close up. Alternatively we |
| - could use an indices array, and then only send 8 verts, but not sure that |
| - would be faster. |
| - */ |
| -static void setStrokeRectStrip(SkPoint verts[10], SkRect rect, |
| - SkScalar width) { |
| - const SkScalar rad = SkScalarHalf(width); |
| - rect.sort(); |
| - |
| - 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]; |
| -} |
| - |
| static inline bool is_irect(const SkRect& r) { |
| return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) && |
| SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom); |
| @@ -510,6 +490,178 @@ 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) { |
| + return SkNEW_ARGS(StrokeRectBatch, (geometry)); |
| + } |
| + |
| + const char* name() const SK_OVERRIDE { return "StrokeRectBatch"; } |
| + |
| + void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { |
| + // When this is called on a batch, there is only one geometry bundle |
| + out->setKnownFourComponents(fGeoData[0].fColor); |
| + } |
| + |
| + void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE { |
| + out->setKnownSingleComponent(0xff); |
| + } |
| + |
| + void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { |
| + // Handle any color overrides |
| + if (init.fColorIgnored) { |
| + fGeoData[0].fColor = GrColor_ILLEGAL; |
| + } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
| + fGeoData[0].fColor = init.fOverrideColor; |
| + } |
| + |
| + // setup batch properties |
| + fBatch.fColorIgnored = init.fColorIgnored; |
| + fBatch.fColor = fGeoData[0].fColor; |
| + fBatch.fUsesLocalCoords = init.fUsesLocalCoords; |
| + fBatch.fCoverageIgnored = init.fCoverageIgnored; |
| + } |
| + |
| + void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE { |
| + SkAutoTUnref<const GrGeometryProcessor> gp( |
| + GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType, |
| + this->color(), |
| + this->viewMatrix(), |
| + SkMatrix::I())); |
| + |
| + batchTarget->initDraw(gp, pipeline); |
| + |
| + // 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 |
| + GrPipelineInfo init; |
| + init.fColorIgnored = fBatch.fColorIgnored; |
| + init.fOverrideColor = GrColor_ILLEGAL; |
| + init.fCoverageIgnored = fBatch.fCoverageIgnored; |
| + init.fUsesLocalCoords = this->usesLocalCoords(); |
| + gp->initBatchTracker(batchTarget->currentBatchTracker(), init); |
| + |
| + 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* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, |
| + vertexCount, |
| + &vertexBuffer, |
| + &firstVertex); |
| + |
| + SkPoint* vertex = reinterpret_cast<SkPoint*>(vertices); |
| + |
| + 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); |
| + } |
| + |
| + 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); |
| + batchTarget->draw(drawInfo); |
| + } |
| + |
| + SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
| + |
| +private: |
| + StrokeRectBatch(const Geometry& geometry) { |
| + this->initClassID<StrokeRectBatch>(); |
| + |
| + fBatch.fHairline = geometry.fStrokeWidth == 0; |
| + |
| + fGeoData.push_back(geometry); |
| + } |
| + |
| + /* 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 |
|
robertphillips
2015/02/27 17:37:37
Shouldn't this be rect.width()/2 and rect.height()
|
| + //SkASSERT(rad < rect.width() && rad < rect.height()); |
| + |
| + 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 onCombineIfPossible(GrBatch* t) SK_OVERRIDE { |
|
robertphillips
2015/02/27 17:37:37
missing space here ?
|
| + // 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 GrContext::drawRect(GrRenderTarget* rt, |
| const GrClip& clip, |
| const GrPaint& paint, |
| @@ -597,47 +749,19 @@ void GrContext::drawRect(GrRenderTarget* rt, |
| } |
| if (width >= 0) { |
| - // TODO: consider making static vertex buffers for these cases. |
| - // Hairline could be done by just adding closing vertex to |
| - // unitSquareVertexBuffer() |
| - |
| - static const int worstCaseVertCount = 10; |
| - SkAutoTUnref<const GrGeometryProcessor> gp( |
| - GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType, |
| - color, |
| - viewMatrix, |
| - SkMatrix::I())); |
| - GrDrawTarget::AutoReleaseGeometry geo(target, |
| - worstCaseVertCount, |
| - gp->getVertexStride(), |
| - 0); |
| - SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
| - |
| - if (!geo.succeeded()) { |
| - SkDebugf("Failed to get space for vertices!\n"); |
| - return; |
| - } |
| - |
| - GrPrimitiveType primType; |
| - int vertCount; |
| - SkPoint* vertex = geo.positions(); |
| - |
| - if (width > 0) { |
| - vertCount = 10; |
| - primType = kTriangleStrip_GrPrimitiveType; |
| - setStrokeRectStrip(vertex, rect, width); |
| - } else { |
| - // hairline |
| - vertCount = 5; |
| - primType = kLineStrip_GrPrimitiveType; |
| - vertex[0].set(rect.fLeft, rect.fTop); |
| - vertex[1].set(rect.fRight, rect.fTop); |
| - vertex[2].set(rect.fRight, rect.fBottom); |
| - vertex[3].set(rect.fLeft, rect.fBottom); |
| - vertex[4].set(rect.fLeft, rect.fTop); |
| - } |
| - |
| - target->drawNonIndexed(&pipelineBuilder, gp, primType, 0, vertCount); |
| + StrokeRectBatch::Geometry geometry; |
| + geometry.fViewMatrix = viewMatrix; |
| + geometry.fColor = color; |
| + geometry.fRect = rect; |
| + geometry.fStrokeWidth = width; |
| + |
| + SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry)); |
| + |
| + SkRect bounds = rect; |
| + SkScalar rad = SkScalarHalf(width); |
| + bounds.outset(rad, rad); |
| + viewMatrix.mapRect(&bounds); |
| + target->drawBatch(&pipelineBuilder, batch, &bounds); |
| } else { |
| // filled BW rect |
| target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect); |
| @@ -669,8 +793,8 @@ void GrContext::drawNonAARectToRect(GrRenderTarget* rt, |
| localMatrix); |
| } |
| -static const GrGeometryProcessor* set_vertex_attributes(const SkPoint* texCoords, |
| - const GrColor* colors, |
| +static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords, |
| + bool hasColors, |
| int* colorOffset, |
| int* texOffset, |
| GrColor color, |
| @@ -678,21 +802,268 @@ static const GrGeometryProcessor* set_vertex_attributes(const SkPoint* texCoords |
| *texOffset = -1; |
| *colorOffset = -1; |
| uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; |
| - if (texCoords && colors) { |
| + if (hasLocalCoords && hasColors) { |
| *colorOffset = sizeof(SkPoint); |
| *texOffset = sizeof(SkPoint) + sizeof(GrColor); |
| flags |= GrDefaultGeoProcFactory::kColor_GPType | |
| GrDefaultGeoProcFactory::kLocalCoord_GPType; |
| - } else if (texCoords) { |
| + } else if (hasLocalCoords) { |
| *texOffset = sizeof(SkPoint); |
| flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType; |
| - } else if (colors) { |
| + } else if (hasColors) { |
| *colorOffset = sizeof(SkPoint); |
| flags |= GrDefaultGeoProcFactory::kColor_GPType; |
| } |
| return GrDefaultGeoProcFactory::Create(flags, color, viewMatrix, SkMatrix::I()); |
| } |
| +class DrawVerticesBatch : public GrBatch { |
| +public: |
| + struct Geometry { |
| + GrColor fColor; |
| + SkTDArray<SkPoint> fPositions; |
| + SkTDArray<uint16_t> fIndices; |
| + SkTDArray<GrColor> fColors; |
| + SkTDArray<SkPoint> fLocalCoords; |
| + }; |
| + |
| + static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveType, |
| + const SkMatrix& viewMatrix, |
| + const SkPoint* positions, int vertexCount, |
| + const uint16_t* indices, int indexCount, |
| + const GrColor* colors, const SkPoint* localCoords) { |
| + return SkNEW_ARGS(DrawVerticesBatch, (geometry, primitiveType, viewMatrix, positions, |
| + vertexCount, indices, indexCount, colors, |
| + localCoords)); |
| + } |
| + |
| + const char* name() const SK_OVERRIDE { return "DrawVerticesBatch"; } |
| + |
| + void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { |
| + // When this is called on a batch, there is only one geometry bundle |
| + if (this->hasColors()) { |
| + out->setUnknownFourComponents(); |
| + } else { |
| + out->setKnownFourComponents(fGeoData[0].fColor); |
| + } |
| + } |
| + |
| + void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE { |
| + out->setUnknownSingleComponent(); |
| + } |
| + |
| + void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { |
| + // Handle any color overrides |
| + if (init.fColorIgnored) { |
| + fGeoData[0].fColor = GrColor_ILLEGAL; |
| + } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
| + fGeoData[0].fColor = init.fOverrideColor; |
| + } |
| + |
| + // setup batch properties |
| + fBatch.fColorIgnored = init.fColorIgnored; |
| + fBatch.fColor = fGeoData[0].fColor; |
| + fBatch.fUsesLocalCoords = init.fUsesLocalCoords; |
| + fBatch.fCoverageIgnored = init.fCoverageIgnored; |
| + } |
| + |
| + void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE { |
| + int colorOffset = -1, texOffset = -1; |
| + SkAutoTUnref<const GrGeometryProcessor> gp( |
| + set_vertex_attributes(this->hasLocalCoords(), this->hasColors(), &colorOffset, |
| + &texOffset, this->color(), this->viewMatrix())); |
| + |
| + batchTarget->initDraw(gp, pipeline); |
| + |
| + // 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 |
| + GrPipelineInfo init; |
| + init.fColorIgnored = fBatch.fColorIgnored; |
| + init.fOverrideColor = GrColor_ILLEGAL; |
| + init.fCoverageIgnored = fBatch.fCoverageIgnored; |
| + init.fUsesLocalCoords = this->usesLocalCoords(); |
| + gp->initBatchTracker(batchTarget->currentBatchTracker(), init); |
| + |
| + size_t vertexStride = gp->getVertexStride(); |
| + |
| + SkASSERT(vertexStride == sizeof(SkPoint) + (this->hasLocalCoords() ? sizeof(SkPoint) : 0) |
| + + (this->hasColors() ? sizeof(GrColor) : 0)); |
| + |
| + int instanceCount = fGeoData.count(); |
| + |
| + const GrVertexBuffer* vertexBuffer; |
| + int firstVertex; |
| + |
| + void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, |
| + this->vertexCount(), |
| + &vertexBuffer, |
| + &firstVertex); |
| + |
| + const GrIndexBuffer* indexBuffer; |
| + int firstIndex; |
| + |
| + void* indices = NULL; |
| + if (this->hasIndices()) { |
| + indices = batchTarget->indexPool()->makeSpace(this->indexCount(), |
| + &indexBuffer, |
| + &firstIndex); |
| + } |
| + |
| + int indexOffset = 0; |
| + int vertexOffset = 0; |
| + for (int i = 0; i < instanceCount; i++) { |
| + const Geometry& args = fGeoData[i]; |
| + |
|
robertphillips
2015/02/27 17:37:37
interleaved ?
|
| + // TODO we can actually cache this interleave and then just memcopy |
| + if (this->hasIndices()) { |
| + for (int j = 0; j < args.fIndices.count(); ++j, ++indexOffset) { |
| + *((uint16_t*)indices + indexOffset) = args.fIndices[j] + vertexOffset; |
| + } |
| + } |
| + |
| + for (int j = 0; j < args.fPositions.count(); ++j) { |
| + *((SkPoint*)vertices) = args.fPositions[j]; |
| + if (this->hasColors()) { |
| + *(GrColor*)((intptr_t)vertices + colorOffset) = args.fColors[j]; |
| + } |
| + if (this->hasLocalCoords()) { |
| + *(SkPoint*)((intptr_t)vertices + texOffset) = args.fLocalCoords[j]; |
| + } |
| + vertices = (void*)((intptr_t)vertices + vertexStride); |
| + vertexOffset++; |
| + } |
| + } |
| + |
| + 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()); |
| + } else { |
| + drawInfo.setStartIndex(0); |
| + drawInfo.setIndexCount(0); |
| + } |
| + batchTarget->draw(drawInfo); |
| + } |
| + |
| + SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
| + |
| +private: |
| + DrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType, |
| + const SkMatrix& viewMatrix, |
| + const SkPoint* positions, int vertexCount, |
| + const uint16_t* indices, int indexCount, |
| + const GrColor* colors, const SkPoint* localCoords) { |
| + this->initClassID<DrawVerticesBatch>(); |
| + SkASSERT(positions); |
| + |
| + fBatch.fViewMatrix = viewMatrix; |
| + Geometry& installedGeo = fGeoData.push_back(geometry); |
| + |
| + installedGeo.fPositions.append(vertexCount, positions); |
| + if (indices) { |
| + installedGeo.fIndices.append(indexCount, indices); |
| + fBatch.fHasIndices = true; |
| + } else { |
| + fBatch.fHasIndices = false; |
| + } |
| + |
| + if (colors) { |
| + installedGeo.fColors.append(vertexCount, colors); |
| + fBatch.fHasColors = true; |
| + } else { |
| + fBatch.fHasColors = false; |
| + } |
| + |
| + if (localCoords) { |
| + installedGeo.fLocalCoords.append(vertexCount, localCoords); |
| + fBatch.fHasLocalCoords = true; |
| + } else { |
| + fBatch.fHasLocalCoords = false; |
| + } |
| + fBatch.fVertexCount = vertexCount; |
| + fBatch.fIndexCount = indexCount; |
| + fBatch.fPrimitiveType = primitiveType; |
| + } |
| + |
| + GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; } |
| + bool batchablePrimitiveType() const { |
| + return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType || |
| + kLines_GrPrimitiveType == fBatch.fPrimitiveType || |
| + kPoints_GrPrimitiveType == fBatch.fPrimitiveType; |
| + } |
| + GrColor color() const { return fBatch.fColor; } |
| + bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
| + bool colorIgnored() const { return fBatch.fColorIgnored; } |
| + const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
| + bool hasColors() const { return fBatch.fHasColors; } |
| + bool hasIndices() const { return fBatch.fHasIndices; } |
| + bool hasLocalCoords() const { return fBatch.fHasLocalCoords; } |
| + int vertexCount() const { return fBatch.fVertexCount; } |
| + int indexCount() const { return fBatch.fIndexCount; } |
| + |
| + bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { |
| + DrawVerticesBatch* that = t->cast<DrawVerticesBatch>(); |
| + |
| + if (!this->batchablePrimitiveType() || this->primitiveType() != that->primitiveType()) { |
| + return false; |
| + } |
| + |
| + SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); |
| + |
| + // We currently use a uniform viewmatrix for this batch |
| + if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
| + return false; |
| + } |
| + |
| + if (this->hasColors() != that->hasColors()) { |
| + return false; |
| + } |
| + |
| + if (this->hasIndices() != that->hasIndices()) { |
| + return false; |
| + } |
| + |
| + if (this->hasLocalCoords() != that->hasLocalCoords()) { |
| + return false; |
| + } |
| + |
| + if (!this->hasColors() && this->color() != that->color()) { |
| + return false; |
| + } |
| + |
| + if (this->color() != that->color()) { |
| + fBatch.fColor = GrColor_ILLEGAL; |
| + } |
| + fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); |
| + fBatch.fVertexCount += that->vertexCount(); |
| + fBatch.fIndexCount += that->indexCount(); |
| + return true; |
| + } |
| + |
| + struct BatchTracker { |
| + GrPrimitiveType fPrimitiveType; |
| + SkMatrix fViewMatrix; |
| + GrColor fColor; |
| + bool fUsesLocalCoords; |
| + bool fColorIgnored; |
| + bool fCoverageIgnored; |
| + bool fHasColors; |
| + bool fHasIndices; |
| + bool fHasLocalCoords; |
| + int fVertexCount; |
| + int fIndexCount; |
| + }; |
| + |
| + BatchTracker fBatch; |
| + SkSTArray<1, Geometry, true> fGeoData; |
| +}; |
| + |
| void GrContext::drawVertices(GrRenderTarget* rt, |
| const GrClip& clip, |
| const GrPaint& paint, |
| @@ -716,43 +1087,15 @@ void GrContext::drawVertices(GrRenderTarget* rt, |
| GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target); |
| - int colorOffset = -1, texOffset = -1; |
| - SkAutoTUnref<const GrGeometryProcessor> gp( |
| - set_vertex_attributes(texCoords, colors, &colorOffset, &texOffset, |
| - paint.getColor(), viewMatrix)); |
| + DrawVerticesBatch::Geometry geometry; |
| + geometry.fColor = paint.getColor(); |
| - size_t vertexStride = gp->getVertexStride(); |
| - SkASSERT(vertexStride == sizeof(SkPoint) + (SkToBool(texCoords) ? sizeof(SkPoint) : 0) |
| - + (SkToBool(colors) ? sizeof(GrColor) : 0)); |
| - if (!geo.set(target, vertexCount, vertexStride, indexCount)) { |
| - SkDebugf("Failed to get space for vertices!\n"); |
| - return; |
| - } |
| - void* curVertex = geo.vertices(); |
| - |
| - for (int i = 0; i < vertexCount; ++i) { |
| - *((SkPoint*)curVertex) = positions[i]; |
| + SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveType, viewMatrix, |
| + positions, vertexCount, indices, |
| + indexCount,colors, texCoords)); |
| - if (texOffset >= 0) { |
| - *(SkPoint*)((intptr_t)curVertex + texOffset) = texCoords[i]; |
| - } |
| - if (colorOffset >= 0) { |
| - *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i]; |
| - } |
| - curVertex = (void*)((intptr_t)curVertex + vertexStride); |
| - } |
| - |
| - // we don't currently apply offscreen AA to this path. Need improved |
| - // management of GrDrawTarget's geometry to avoid copying points per-tile. |
| - if (indices) { |
| - uint16_t* curIndex = (uint16_t*)geo.indices(); |
| - for (int i = 0; i < indexCount; ++i) { |
| - curIndex[i] = indices[i]; |
| - } |
| - target->drawIndexed(&pipelineBuilder, gp, primitiveType, 0, 0, vertexCount, indexCount); |
| - } else { |
| - target->drawNonIndexed(&pipelineBuilder, gp, primitiveType, 0, vertexCount); |
| - } |
| + // TODO figure out bounds |
| + target->drawBatch(&pipelineBuilder, batch, NULL); |
| } |
| /////////////////////////////////////////////////////////////////////////////// |