Index: src/gpu/GrContext.cpp |
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp |
index 85ea9cab28780978486f62233ed460a5a799b2ab..679ee84cad84394661d6d603e18efba9e93538d9 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 |
+ //SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2); |
+ |
+ verts[0].set(rect.fLeft + rad, rect.fTop + rad); |
+ verts[1].set(rect.fLeft - rad, rect.fTop - rad); |
+ verts[2].set(rect.fRight - rad, rect.fTop + rad); |
+ verts[3].set(rect.fRight + rad, rect.fTop - rad); |
+ verts[4].set(rect.fRight - rad, rect.fBottom - rad); |
+ verts[5].set(rect.fRight + rad, rect.fBottom + rad); |
+ verts[6].set(rect.fLeft + rad, rect.fBottom - rad); |
+ verts[7].set(rect.fLeft - rad, rect.fBottom + rad); |
+ verts[8] = verts[0]; |
+ verts[9] = verts[1]; |
+ } |
+ |
+ |
+ GrColor color() const { return fBatch.fColor; } |
+ bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
+ bool colorIgnored() const { return fBatch.fColorIgnored; } |
+ const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
+ bool hairline() const { return fBatch.fHairline; } |
+ |
+ bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { |
+ // 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]; |
+ |
+ // TODO we can actually cache this interleaved 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); |
} |
/////////////////////////////////////////////////////////////////////////////// |