Chromium Code Reviews| Index: src/gpu/GrDrawContext.cpp |
| diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp |
| index 40188c575b8c00460a06c7a1178b1e8ff1ae6e82..c222c1857c6b3d1da69111691bd3fbadecd68835 100644 |
| --- a/src/gpu/GrDrawContext.cpp |
| +++ b/src/gpu/GrDrawContext.cpp |
| @@ -10,6 +10,7 @@ |
| #include "GrAtlasTextContext.h" |
| #include "GrBatch.h" |
| #include "GrBatchTest.h" |
| +#include "GrColor.h" |
| #include "GrDefaultGeoProcFactory.h" |
| #include "GrDrawContext.h" |
| #include "GrOvalRenderer.h" |
| @@ -19,6 +20,9 @@ |
| #include "GrStrokeRectBatch.h" |
| #include "GrStencilAndCoverTextContext.h" |
| +#include "SkGr.h" |
| +#include "SkRSXform.h" |
| + |
| #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext) |
| #define RETURN_IF_ABANDONED if (!fDrawTarget) { return; } |
| #define RETURN_FALSE_IF_ABANDONED if (!fDrawTarget) { return false; } |
| @@ -690,6 +694,269 @@ void GrDrawContext::drawVertices(GrRenderTarget* rt, |
| /////////////////////////////////////////////////////////////////////////////// |
| +class DrawAtlasBatch : public GrBatch { |
| +public: |
| + struct Geometry { |
| + GrColor fColor; |
| + SkTDArray<SkPoint> fPositions; |
|
robertphillips
2015/08/07 13:36:37
Can we remove 'fIndices' ?
jvanverth1
2015/08/07 15:55:17
Done.
|
| + 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 GrColor* colors, const SkPoint* localCoords, |
| + const SkRect& bounds) { |
| + return SkNEW_ARGS(DrawAtlasBatch, (geometry, primitiveType, viewMatrix, positions, |
| + vertexCount, colors, localCoords, bounds)); |
| + } |
| + |
| + const char* name() const override { return "DrawAtlasBatch"; } |
| + |
| + void getInvariantOutputColor(GrInitInvariantOutput* out) const 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 override { |
| + out->setKnownSingleComponent(0xff); |
| + } |
| + |
| + void initBatchTracker(const GrPipelineInfo& init) override { |
| + // Handle any color overrides |
| + if (!init.readsColor()) { |
| + fGeoData[0].fColor = GrColor_ILLEGAL; |
| + } |
| + init.getOverrideColorIfSet(&fGeoData[0].fColor); |
| + |
| + // setup batch properties |
| + fBatch.fColorIgnored = !init.readsColor(); |
| + fBatch.fColor = fGeoData[0].fColor; |
| + fBatch.fUsesLocalCoords = init.readsLocalCoords(); |
| + fBatch.fCoverageIgnored = !init.readsCoverage(); |
| + } |
| + |
| + void generateGeometry(GrBatchTarget* batchTarget) override { |
| + int colorOffset = -1, texOffset = -1; |
| + // Setup geometry processor |
| + SkAutoTUnref<const GrGeometryProcessor> gp( |
| + set_vertex_attributes(true, this->hasColors(), &colorOffset, |
| + &texOffset, this->color(), this->viewMatrix(), |
| + this->coverageIgnored())); |
| + |
| + batchTarget->initDraw(gp, this->pipeline()); |
| + |
| + int instanceCount = fGeoData.count(); |
| + size_t vertexStride = gp->getVertexStride(); |
| + SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(SkPoint) |
| + + (this->hasColors() ? sizeof(GrColor) : 0)); |
| + |
| + QuadHelper helper; |
| + int numQuads = this->vertexCount()/4; |
| + void* verts = helper.init(batchTarget, vertexStride, numQuads); |
| + if (!verts) { |
| + SkDebugf("Could not allocate vertices\n"); |
| + return; |
| + } |
| + |
| + int vertexOffset = 0; |
| + for (int i = 0; i < instanceCount; i++) { |
| + const Geometry& args = fGeoData[i]; |
| + |
| + for (int j = 0; j < args.fPositions.count(); ++j) { |
| + *((SkPoint*)verts) = args.fPositions[j]; |
| + if (this->hasColors()) { |
| + *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j]; |
| + } |
| + *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j]; |
| + verts = (void*)((intptr_t)verts + vertexStride); |
| + vertexOffset++; |
| + } |
| + } |
| + helper.issueDraw(batchTarget); |
| + } |
| + |
| + SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
| + |
| +private: |
| + DrawAtlasBatch(const Geometry& geometry, GrPrimitiveType primitiveType, |
| + const SkMatrix& viewMatrix, |
| + const SkPoint* positions, int vertexCount, |
| + const GrColor* colors, const SkPoint* localCoords, const SkRect& bounds) { |
| + this->initClassID<DrawVerticesBatch>(); |
| + SkASSERT(positions); |
| + SkASSERT(localCoords); |
| + |
| + fBatch.fViewMatrix = viewMatrix; |
| + Geometry& installedGeo = fGeoData.push_back(geometry); |
| + |
| + installedGeo.fPositions.append(vertexCount, positions); |
| + |
| + if (colors) { |
| + installedGeo.fColors.append(vertexCount, colors); |
| + fBatch.fHasColors = true; |
| + } else { |
| + fBatch.fHasColors = false; |
| + } |
| + |
| + installedGeo.fLocalCoords.append(vertexCount, localCoords); |
| + fBatch.fVertexCount = vertexCount; |
| + fBatch.fPrimitiveType = primitiveType; |
| + |
| + this->setBounds(bounds); |
| + } |
| + |
| + GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; } |
| + bool batchablePrimitiveType() const { |
|
robertphillips
2015/08/07 13:36:38
Don't we always know fPrimitiveType will be kTrian
jvanverth1
2015/08/07 15:55:17
Done.
|
| + return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType || |
|
robertphillips
2015/08/07 13:36:37
tab these over ?
jvanverth1
2015/08/07 15:55:17
Removed.
|
| + kLines_GrPrimitiveType == fBatch.fPrimitiveType || |
| + kPoints_GrPrimitiveType == fBatch.fPrimitiveType; |
| + } |
| + GrColor color() const { return fBatch.fColor; } |
|
robertphillips
2015/08/07 13:36:38
Can we just return true from 'usesLocalCoords' ?
jvanverth1
2015/08/07 15:55:17
Removed.
|
| + 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; } |
| + int vertexCount() const { return fBatch.fVertexCount; } |
| + bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
| + |
| + bool onCombineIfPossible(GrBatch* t) override { |
| + if (!this->pipeline()->isEqual(*t->pipeline())) { |
| + return false; |
| + } |
| + |
| + DrawAtlasBatch* that = t->cast<DrawAtlasBatch>(); |
| + |
|
robertphillips
2015/08/07 13:36:37
Can we skip this check ?
jvanverth1
2015/08/07 15:55:17
Done.
|
| + 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; |
| + } |
| + |
|
robertphillips
2015/08/07 13:36:37
We could, in theory, generate white vertex colors
jvanverth1
2015/08/07 15:55:17
It's possible, though, so for now I think I'll lea
|
| + if (this->hasColors() != that->hasColors()) { |
| + 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(); |
| + |
| + this->joinBounds(that->bounds()); |
| + return true; |
| + } |
| + |
| + struct BatchTracker { |
| + GrPrimitiveType fPrimitiveType; |
| + SkMatrix fViewMatrix; |
| + GrColor fColor; |
| + bool fUsesLocalCoords; |
| + bool fColorIgnored; |
| + bool fCoverageIgnored; |
| + bool fHasColors; |
| + int fVertexCount; |
| + }; |
| + |
| + BatchTracker fBatch; |
| + SkSTArray<1, Geometry, true> fGeoData; |
| +}; |
| + |
| +void GrDrawContext::drawAtlas(GrRenderTarget* rt, |
| + const GrClip& clip, |
| + const GrPaint& paint, |
| + const SkMatrix& viewMatrix, |
| + int spriteCount, |
| + const SkRSXform xform[], |
| + const SkRect texRect[], |
| + const SkColor colors[]) { |
| + RETURN_IF_ABANDONED |
| + AutoCheckFlush acf(fContext); |
| + if (!this->prepareToDraw(rt)) { |
| + return; |
| + } |
| + |
| + GrPipelineBuilder pipelineBuilder(paint, rt, clip); |
| + |
| + // TODO clients should give us bounds |
| + SkRect bounds; |
|
robertphillips
2015/08/07 13:36:38
Hmmm ... I think you have to transform each texRec
jvanverth1
2015/08/07 15:55:17
Done. Moved to after we build the vertex locations
|
| + if (!bounds.setBoundsCheck(reinterpret_cast<const SkPoint*>(texRect), 2*spriteCount)) { |
| + SkDebugf("drawAtlas call empty bounds\n"); |
| + return; |
| + } |
| + |
| + viewMatrix.mapRect(&bounds); |
| + |
| + // If we don't have AA then we outset for a half pixel in each direction to account for |
| + // snapping |
| + if (!paint.isAntiAlias()) { |
| + bounds.outset(0.5f, 0.5f); |
| + } |
| + |
|
robertphillips
2015/08/07 13:36:38
Is the plan to interleave here ?
jvanverth1
2015/08/07 15:55:17
The plan is that the interleaving will happen when
|
| + // now build the renderable geometry |
| + const int vertCount = spriteCount * 4; |
| + SkAutoTMalloc<SkPoint> vertStorage(vertCount * 2); |
| + SkPoint* verts = vertStorage.get(); |
| + SkPoint* texs = verts + vertCount; |
| + |
| + for (int i = 0; i < spriteCount; ++i) { |
| + xform[i].toQuad(texRect[i].width(), texRect[i].height(), verts); |
| + texRect[i].toQuad(texs); |
| + verts += 4; |
| + texs += 4; |
| + } |
| + |
| + SkAutoTMalloc<GrColor> colorStorage; |
| + GrColor* vertCols = NULL; |
| + if (colors) { |
| + colorStorage.reset(vertCount); |
| + vertCols = colorStorage.get(); |
| + |
| + int paintAlpha = GrColorUnpackA(paint.getColor()); |
| + |
| + // need to convert byte order and from non-PM to PM |
| + for (int i = 0; i < spriteCount; ++i) { |
| + SkColor color = colors[i]; |
| + if (paintAlpha != 255) { |
| + color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paintAlpha)); |
| + } |
| + GrColor grColor = SkColor2GrColor(color); |
| + |
|
robertphillips
2015/08/07 13:36:37
:(
jvanverth1
2015/08/07 15:55:17
Acknowledged.
|
| + vertCols[0] = vertCols[1] = vertCols[2] = vertCols[3] = grColor; |
| + vertCols += 4; |
| + } |
| + } |
| + |
| + verts = vertStorage.get(); |
| + texs = verts + vertCount; |
| + vertCols = colorStorage.get(); |
| + |
| + DrawAtlasBatch::Geometry geometry; |
| + geometry.fColor = paint.getColor(); |
| + SkAutoTUnref<GrBatch> batch(DrawAtlasBatch::Create(geometry, kTriangles_GrPrimitiveType, |
| + viewMatrix, verts, vertCount, vertCols, texs, |
| + bounds)); |
| + |
| + fDrawTarget->drawBatch(pipelineBuilder, batch); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| void GrDrawContext::drawRRect(GrRenderTarget*rt, |
| const GrClip& clip, |
| const GrPaint& paint, |