diff options
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.cpp | 68 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.h | 8 | ||||
-rw-r--r-- | src/gpu/batches/GrDrawPathBatch.cpp | 188 | ||||
-rw-r--r-- | src/gpu/batches/GrDrawPathBatch.h | 149 |
4 files changed, 256 insertions, 157 deletions
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp index 77960dbe7a..d28f1a803a 100644 --- a/src/gpu/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/GrStencilAndCoverTextContext.cpp @@ -233,7 +233,7 @@ void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, class GrStencilAndCoverTextContext::FallbackBlobBuilder { public: - FallbackBlobBuilder() : fBuffIdx(0) {} + FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {} bool isInitialized() const { return SkToBool(fBuilder); } @@ -241,7 +241,7 @@ public: void appendGlyph(uint16_t glyphId, const SkPoint& pos); - const SkTextBlob* buildIfInitialized(); + const SkTextBlob* buildIfNeeded(int* count); private: enum { kWriteBufferSize = 1024 }; @@ -251,6 +251,7 @@ private: SkAutoTDelete<SkTextBlobBuilder> fBuilder; SkPaint fFont; int fBuffIdx; + int fCount; uint16_t fGlyphIds[kWriteBufferSize]; SkPoint fPositions[kWriteBufferSize]; }; @@ -261,6 +262,7 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) : fStroke(fontAndStroke), fFont(fontAndStroke), fTotalGlyphCount(0), + fFallbackGlyphCount(0), fDetachedGlyphCache(nullptr), fLastDrawnGlyphsID(SK_InvalidUniqueID) { SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. @@ -339,9 +341,6 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) memcpy(&builder[2 + strokeDataCount], desc, desc->getLength()); } } - - // When drawing from canonically sized paths, the actual local coords are fTextRatio * coords. - fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio); } GrStencilAndCoverTextContext::TextRun::~TextRun() { @@ -355,8 +354,9 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by SkGlyphCache* glyphCache = this->getGlyphCache(); SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); - fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransformType, - fTotalGlyphCount = fFont.countText(text, byteLength))); + fTotalGlyphCount = fFont.countText(text, byteLength); + fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType, + fTotalGlyphCount)); const char* stop = text + byteLength; @@ -407,7 +407,7 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); } - fFallbackTextBlob.reset(fallback.buildIfInitialized()); + fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); } void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength, @@ -419,8 +419,9 @@ void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t SkGlyphCache* glyphCache = this->getGlyphCache(); SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); - fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransformType, - fTotalGlyphCount = fFont.countText(text, byteLength))); + fTotalGlyphCount = fFont.countText(text, byteLength); + fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType, + fTotalGlyphCount)); const char* stop = text + byteLength; @@ -440,7 +441,7 @@ void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t pos += scalarsPerPosition; } - fFallbackTextBlob.reset(fallback.buildIfInitialized()); + fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); } GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx) const { @@ -470,8 +471,8 @@ inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl } fallback->appendGlyph(glyph.getGlyphID(), pos); } else { - float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y() }; - fDraw->append(glyph.getGlyphID(), translate); + fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(), + fTextInverseRatio * pos.y()); } } @@ -484,10 +485,10 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, const SkIRect& clipBounds, GrTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const { - SkASSERT(fDraw); + SkASSERT(fInstanceData); SkASSERT(dc->accessRenderTarget()->isStencilBufferMultisampled() || !fFont.isAntiAlias()); - if (fDraw->count()) { + if (fInstanceData->count()) { pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias()); GR_STATIC_CONST_SAME_STENCIL(kStencilPass, @@ -503,18 +504,10 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { // Either this is the first draw or the glyphs object was purged since last draw. - glyphs->loadPathsIfNeeded(fDraw->indices(), fDraw->count()); + glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count()); fLastDrawnGlyphsID = glyphs->getUniqueID(); } - SkMatrix drawMatrix(viewMatrix); - drawMatrix.preTranslate(x, y); - drawMatrix.preScale(fTextRatio, fTextRatio); - - SkMatrix& localMatrix = fLocalMatrixTemplate; - localMatrix.setTranslateX(x); - localMatrix.setTranslateY(y); - // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy // the entire dst. Realistically this is a moot point, because any context that supports // NV_path_rendering will also support NV_blend_equation_advanced. @@ -524,8 +517,9 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, pipelineBuilder->getRenderTarget()->height()); SkAutoTUnref<GrDrawPathBatchBase> batch( - GrDrawPathRangeBatch::Create(drawMatrix, localMatrix, color, - GrPathRendering::kWinding_FillType, glyphs, fDraw, + GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRatio * x, + fTextInverseRatio * y, color, + GrPathRendering::kWinding_FillType, glyphs, fInstanceData, bounds)); dc->drawPathBatch(*pipelineBuilder, batch); @@ -559,11 +553,11 @@ void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const { } size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const { - size_t size = sizeof(TextRun) + - fGlyphPathsKey.size() + - fTotalGlyphCount * (sizeof(uint16_t) + 2 * sizeof(float)); - if (fDraw) { - size += sizeof(GrPathRangeDraw); + size_t size = sizeof(TextRun) + fGlyphPathsKey.size(); + // The instance data always reserves enough space for every glyph. + size += (fTotalGlyphCount + fFallbackGlyphCount) * (sizeof(uint16_t) + 2 * sizeof(float)); + if (fInstanceData) { + size += sizeof(InstanceData); } if (fFallbackTextBlob) { size += sizeof(SkTextBlob); @@ -596,6 +590,7 @@ void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t gly fGlyphIds[fBuffIdx] = glyphId; fPositions[fBuffIdx] = pos; fBuffIdx++; + fCount++; } void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { @@ -611,10 +606,11 @@ void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { fBuffIdx = 0; } -const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInitialized() { - if (!this->isInitialized()) { - return nullptr; +const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeeded(int *count) { + *count = fCount; + if (fCount) { + this->flush(); + return fBuilder->build(); } - this->flush(); - return fBuilder->build(); + return nullptr; } diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h index 7716c78405..dab71e0578 100644 --- a/src/gpu/GrStencilAndCoverTextContext.h +++ b/src/gpu/GrStencilAndCoverTextContext.h @@ -14,11 +14,11 @@ #include "SkTHash.h" #include "SkTInternalLList.h" #include "SkTLList.h" +#include "batches/GrDrawPathBatch.h" class GrTextStrike; class GrPath; class SkSurfaceProps; -class GrPathRangeDraw; /* * This class implements text rendering using stencil and cover path rendering @@ -75,6 +75,8 @@ private: size_t computeSizeInCache() const; private: + typedef GrDrawPathRangeBatch::InstanceData InstanceData; + SkGlyphCache* getGlyphCache() const; GrPathRange* createGlyphs(GrContext*) const; void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*); @@ -86,11 +88,11 @@ private: bool fUsingRawGlyphPaths; GrUniqueKey fGlyphPathsKey; int fTotalGlyphCount; - SkAutoTUnref<GrPathRangeDraw> fDraw; + SkAutoTUnref<InstanceData> fInstanceData; + int fFallbackGlyphCount; SkAutoTUnref<const SkTextBlob> fFallbackTextBlob; mutable SkGlyphCache* fDetachedGlyphCache; mutable uint32_t fLastDrawnGlyphsID; - mutable SkMatrix fLocalMatrixTemplate; }; // Text blobs/caches. diff --git a/src/gpu/batches/GrDrawPathBatch.cpp b/src/gpu/batches/GrDrawPathBatch.cpp index c2007ce933..3264c0fbaf 100644 --- a/src/gpu/batches/GrDrawPathBatch.cpp +++ b/src/gpu/batches/GrDrawPathBatch.cpp @@ -7,6 +7,10 @@ #include "GrDrawPathBatch.h" +static void pre_translate_transform_values(const float* xforms, + GrPathRendering::PathTransformType type, int count, + SkScalar x, SkScalar y, float* dst); + SkString GrDrawPathBatch::dumpInfo() const { SkString string; string.printf("PATH: 0x%p", fPath.get()); @@ -25,51 +29,59 @@ void GrDrawPathBatch::onDraw(GrBatchFlushState* state) { state->gpu()->pathRendering()->drawPath(args, fPath.get()); } -GrDrawPathRangeBatch::~GrDrawPathRangeBatch() { - for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) { - (*iter.get())->unref(); - } -} - SkString GrDrawPathRangeBatch::dumpInfo() const { SkString string; - string.printf("RANGE: 0x%p COUNTS: [", *fDraws.head()); + string.printf("RANGE: 0x%p COUNTS: [", fPathRange.get()); for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) { - string.appendf("%d ,", (*iter.get())->count()); + string.appendf("%d, ", iter.get()->fInstanceData->count()); } string.remove(string.size() - 2, 2); string.append("]"); return string; } -GrDrawPathRangeBatch::GrDrawPathRangeBatch(const SkMatrix& viewMatrix, const SkMatrix& localMatrix, - GrColor color, GrPathRendering::FillType fill, - GrPathRange* range, GrPathRangeDraw* draw, - const SkRect& bounds) +GrDrawPathRangeBatch::GrDrawPathRangeBatch(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, + SkScalar y, GrColor color, + GrPathRendering::FillType fill, GrPathRange* range, + const InstanceData* instanceData, const SkRect& bounds) : INHERITED(ClassID(), viewMatrix, color, fill) , fPathRange(range) - , fLocalMatrix(localMatrix) { - SkDEBUGCODE(draw->fUsedInBatch = true;) - fDraws.addToHead(SkRef(draw)); - fTotalPathCount = draw->count(); + , fTotalPathCount(instanceData->count()) + , fScale(scale) { + fDraws.addToHead()->set(instanceData, x, y); fBounds = bounds; } bool GrDrawPathRangeBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) { GrDrawPathRangeBatch* that = t->cast<GrDrawPathRangeBatch>(); - if (this->fPathRange.get() != that->fPathRange.get()) { - return false; - } - if (!GrPathRangeDraw::CanMerge(**this->fDraws.head(), **that->fDraws.head())) { + if (this->fPathRange.get() != that->fPathRange.get() || + this->transformType() != that->transformType() || + this->fScale != that->fScale || + this->color() != that->color() || + !this->viewMatrix().cheapEqualTo(that->viewMatrix())) { return false; } if (!GrPipeline::AreEqual(*this->pipeline(), *that->pipeline(), false)) { return false; } - if (this->color() != that->color() || - !this->viewMatrix().cheapEqualTo(that->viewMatrix()) || - !fLocalMatrix.cheapEqualTo(that->fLocalMatrix)) { - return false; + switch (fDraws.head()->fInstanceData->transformType()) { + case GrPathRendering::kNone_PathTransformType: + if (this->fDraws.head()->fX != that->fDraws.head()->fX || + this->fDraws.head()->fY != that->fDraws.head()->fY) { + return false; + } + break; + case GrPathRendering::kTranslateX_PathTransformType: + if (this->fDraws.head()->fY != that->fDraws.head()->fY) { + return false; + } + break; + case GrPathRendering::kTranslateY_PathTransformType: + if (this->fDraws.head()->fX != that->fDraws.head()->fX) { + return false; + } + break; + default: break; } // TODO: Check some other things here. (winding, opaque, pathProc color, vm, ...) // Try to combine this call with the previous DrawPaths. We do this by stenciling all the @@ -85,47 +97,117 @@ bool GrDrawPathRangeBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) { } SkASSERT(!that->overrides().willColorBlendWithDst()); fTotalPathCount += that->fTotalPathCount; - while (GrPathRangeDraw** head = that->fDraws.head()) { - fDraws.addToTail(*head); - // We're stealing that's refs, so pop without unreffing. + while (Draw* head = that->fDraws.head()) { + Draw* draw = fDraws.addToTail(); + draw->fInstanceData.reset(head->fInstanceData.detach()); + draw->fX = head->fX; + draw->fY = head->fY; that->fDraws.popHead(); } return true; } void GrDrawPathRangeBatch::onDraw(GrBatchFlushState* state) { - GrProgramDesc desc; + const Draw& head = *fDraws.head(); + + SkMatrix drawMatrix(this->viewMatrix()); + drawMatrix.preScale(fScale, fScale); + drawMatrix.preTranslate(head.fX, head.fY); + + SkMatrix localMatrix; + localMatrix.setScale(fScale, fScale); + localMatrix.preTranslate(head.fX, head.fY); + SkAutoTUnref<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->overrides(), - this->viewMatrix(), - fLocalMatrix)); + drawMatrix, + localMatrix)); + + GrProgramDesc desc; state->gpu()->buildProgramDesc(&desc, *pathProc, *this->pipeline()); GrPathRendering::DrawPathArgs args(pathProc, this->pipeline(), - &desc, &this->stencilSettings()); + &desc, &this->stencilSettings()); + if (fDraws.count() == 1) { - const GrPathRangeDraw& draw = **fDraws.head(); - state->gpu()->pathRendering()->drawPaths(args, fPathRange.get(), draw.indices(), - GrPathRange::kU16_PathIndexType, draw.transforms(), draw.transformType(), - draw.count()); - return; + const InstanceData& instances = *head.fInstanceData; + state->gpu()->pathRendering()->drawPaths(args, fPathRange.get(), instances.indices(), + GrPathRange::kU16_PathIndexType, + instances.transformValues(), + instances.transformType(), + instances.count()); + } else { + int floatsPerTransform = GrPathRendering::PathTransformSize(this->transformType()); +#if defined(GOOGLE3) + //Stack frame size is limited in GOOGLE3. + SkAutoSTMalloc<512, float> transformStorage(transformSize * fTotalPathCount); + SkAutoSTMalloc<256, uint16_t> indexStorage(fTotalPathCount); +#else + SkAutoSTMalloc<4096, float> transformStorage(floatsPerTransform * fTotalPathCount); + SkAutoSTMalloc<2048, uint16_t> indexStorage(fTotalPathCount); +#endif + int idx = 0; + for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) { + const Draw& draw = *iter.get(); + const InstanceData& instances = *draw.fInstanceData; + memcpy(&indexStorage[idx], instances.indices(), instances.count() * sizeof(uint16_t)); + pre_translate_transform_values(instances.transformValues(), this->transformType(), + instances.count(), + draw.fX - head.fX, draw.fY - head.fY, + &transformStorage[floatsPerTransform * idx]); + idx += instances.count(); + + // TODO: Support mismatched transform types if we start using more types other than 2D. + SkASSERT(instances.transformType() == this->transformType()); + } + SkASSERT(idx == fTotalPathCount); + + state->gpu()->pathRendering()->drawPaths(args, fPathRange.get(), indexStorage, + GrPathRange::kU16_PathIndexType, transformStorage, + this->transformType(), fTotalPathCount); } +} - GrPathRendering::PathTransformType transformType = (*fDraws.head())->transformType(); - int floatsPerTransform = GrPathRendering::PathTransformSize(transformType); - SkAutoSTMalloc<512, float> transformStorage(floatsPerTransform * fTotalPathCount); - SkAutoSTMalloc<256, uint16_t> indexStorage(fTotalPathCount); - uint16_t* indices = indexStorage.get(); - float* transforms = transformStorage.get(); - for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) { - SkASSERT((*iter.get())->transformType() == transformType); - int cnt = (*iter.get())->count(); - memcpy(indices, (*iter.get())->indices(), cnt * sizeof(uint16_t)); - indices += cnt; - memcpy(transforms, (*iter.get())->transforms(), cnt * floatsPerTransform * sizeof(float)); - transforms += cnt * floatsPerTransform; +inline void pre_translate_transform_values(const float* xforms, + GrPathRendering::PathTransformType type, int count, + SkScalar x, SkScalar y, float* dst) { + if (0 == x && 0 == y) { + memcpy(dst, xforms, count * GrPathRendering::PathTransformSize(type) * sizeof(float)); + return; + } + switch (type) { + case GrPathRendering::kNone_PathTransformType: + SkFAIL("Cannot pre-translate kNone_PathTransformType."); + break; + case GrPathRendering::kTranslateX_PathTransformType: + SkASSERT(0 == y); + for (int i = 0; i < count; i++) { + dst[i] = xforms[i] + x; + } + break; + case GrPathRendering::kTranslateY_PathTransformType: + SkASSERT(0 == x); + for (int i = 0; i < count; i++) { + dst[i] = xforms[i] + y; + } + break; + case GrPathRendering::kTranslate_PathTransformType: + for (int i = 0; i < 2 * count; i += 2) { + dst[i] = xforms[i] + x; + dst[i + 1] = xforms[i + 1] + y; + } + break; + case GrPathRendering::kAffine_PathTransformType: + for (int i = 0; i < 6 * count; i += 6) { + dst[i] = xforms[i]; + dst[i + 1] = xforms[i + 1]; + dst[i + 2] = xforms[i] * x + xforms[i + 1] * y + xforms[i + 2]; + dst[i + 3] = xforms[i + 3]; + dst[i + 4] = xforms[i + 4]; + dst[i + 5] = xforms[i + 3] * x + xforms[i + 4] * y + xforms[i + 5]; + } + break; + default: + SkFAIL("Unknown transform type."); + break; } - SkASSERT(indices - indexStorage.get() == fTotalPathCount); - state->gpu()->pathRendering()->drawPaths(args, fPathRange.get(), indexStorage.get(), - GrPathRange::kU16_PathIndexType, transformStorage.get(), transformType, - fTotalPathCount); } diff --git a/src/gpu/batches/GrDrawPathBatch.h b/src/gpu/batches/GrDrawPathBatch.h index fdd3448a73..0b24fe0546 100644 --- a/src/gpu/batches/GrDrawPathBatch.h +++ b/src/gpu/batches/GrDrawPathBatch.h @@ -93,84 +93,91 @@ private: typedef GrDrawPathBatchBase INHERITED; }; -/** - * This could be nested inside the batch class, but for now it must be declarable in a public - * header (GrDrawContext) - */ -class GrPathRangeDraw : public GrNonAtomicRef { -public: - typedef GrPathRendering::PathTransformType TransformType; - - static GrPathRangeDraw* Create(TransformType transformType, int reserveCnt) { - return new GrPathRangeDraw(transformType, reserveCnt); - } - - void append(uint16_t index, float transform[]) { - fTransforms.push_back_n(GrPathRendering::PathTransformSize(fTransformType), transform); - fIndices.push_back(index); - } - - int count() const { return fIndices.count(); } - - TransformType transformType() const { return fTransformType; } - - const float* transforms() const { return fTransforms.begin(); } - - const uint16_t* indices() const { return fIndices.begin(); } - - static bool CanMerge(const GrPathRangeDraw& a, const GrPathRangeDraw& b) { - return a.transformType() == b.transformType(); - } - -private: - GrPathRangeDraw(TransformType transformType, int reserveCnt) - : fTransformType(transformType) - , fIndices(reserveCnt) - , fTransforms(reserveCnt * GrPathRendering::PathTransformSize(transformType)) { - SkDEBUGCODE(fUsedInBatch = false;) - } - - // Reserve space for 64 paths where indices are 16 bit and transforms are translations. - static const int kIndexReserveCnt = 64; - static const int kTransformBufferReserveCnt = 2 * 64; - - GrPathRendering::PathTransformType fTransformType; - SkSTArray<kIndexReserveCnt, uint16_t, true> fIndices; - SkSTArray<kTransformBufferReserveCnt, float, true> fTransforms; - - // To ensure we don't reuse these across batches. -#ifdef SK_DEBUG - bool fUsedInBatch; - friend class GrDrawPathRangeBatch; -#endif - - typedef GrNonAtomicRef INHERITED; -}; - // Template this if we decide to support index types other than 16bit class GrDrawPathRangeBatch final : public GrDrawPathBatchBase { public: + typedef GrPathRendering::PathTransformType TransformType; + DEFINE_BATCH_CLASS_ID + struct InstanceData : public SkNoncopyable { + public: + static InstanceData* Alloc(TransformType transformType, int reserveCnt) { + int transformSize = GrPathRendering::PathTransformSize(transformType); + uint8_t* ptr = (uint8_t*)sk_malloc_throw(Align32(sizeof(InstanceData)) + + Align32(reserveCnt * sizeof(uint16_t)) + + reserveCnt * transformSize * sizeof(float)); + InstanceData* instanceData = (InstanceData*)ptr; + instanceData->fIndices = (uint16_t*)&ptr[Align32(sizeof(InstanceData))]; + instanceData->fTransformValues = (float*)&ptr[Align32(sizeof(InstanceData)) + + Align32(reserveCnt * sizeof(uint16_t))]; + instanceData->fTransformType = transformType; + instanceData->fInstanceCount = 0; + instanceData->fRefCnt = 1; + SkDEBUGCODE(instanceData->fReserveCnt = reserveCnt;) + return instanceData; + } + + // Overload this method if we start using other transform types. + void append(uint16_t index, float x, float y) { + SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType); + SkASSERT(fInstanceCount < fReserveCnt); + fIndices[fInstanceCount] = index; + fTransformValues[2 * fInstanceCount] = x; + fTransformValues[2 * fInstanceCount + 1] = y; + ++fInstanceCount; + } + + TransformType transformType() const { return fTransformType; } + int count() const { return fInstanceCount; } + + const uint16_t* indices() const { return fIndices; } + uint16_t* indices() { return fIndices; } + + const float* transformValues() const { return fTransformValues; } + float* transformValues() { return fTransformValues; } + + void ref() const { ++fRefCnt; } + + void unref() const { + if (0 == --fRefCnt) { + sk_free(const_cast<InstanceData*>(this)); + } + } + + private: + static int Align32(int sizeInBytes) { return (sizeInBytes + 3) & ~3; } + + InstanceData() {} + ~InstanceData() {} + + uint16_t* fIndices; + float* fTransformValues; + TransformType fTransformType; + int fInstanceCount; + mutable int fRefCnt; + SkDEBUGCODE(int fReserveCnt;) + }; + // This can't return a more abstract type because we install the stencil settings late :( - static GrDrawPathBatchBase* Create(const SkMatrix& viewMatrix, const SkMatrix& localMatrix, - GrColor color, GrPathRendering::FillType fill, - GrPathRange* range, GrPathRangeDraw* draw, + static GrDrawPathBatchBase* Create(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, + SkScalar y, GrColor color, GrPathRendering::FillType fill, + GrPathRange* range, const InstanceData* instanceData, const SkRect& bounds) { - return new GrDrawPathRangeBatch(viewMatrix, localMatrix, color, fill, range, draw, + return new GrDrawPathRangeBatch(viewMatrix, scale, x, y, color, fill, range, instanceData, bounds); } - ~GrDrawPathRangeBatch() override; - const char* name() const override { return "DrawPathRange"; } SkString dumpInfo() const override; private: - GrDrawPathRangeBatch(const SkMatrix& viewMatrix, const SkMatrix& localMatrix, GrColor color, - GrPathRendering::FillType fill, GrPathRange* range, - GrPathRangeDraw* draw, const SkRect& bounds); + GrDrawPathRangeBatch(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x, SkScalar y, + GrColor color, GrPathRendering::FillType fill, GrPathRange* range, + const InstanceData* instanceData, const SkRect& bounds); + + TransformType transformType() const { return fDraws.head()->fInstanceData->transformType(); } bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override; @@ -178,12 +185,24 @@ private: void onDraw(GrBatchFlushState* state) override; + struct Draw { + void set(const InstanceData* instanceData, SkScalar x, SkScalar y) { + fInstanceData.reset(SkRef(instanceData)); + fX = x; + fY = y; + } + + SkAutoTUnref<const InstanceData> fInstanceData; + SkScalar fX, fY; + }; + typedef GrPendingIOResource<const GrPathRange, kRead_GrIOType> PendingPathRange; - typedef SkTLList<GrPathRangeDraw*, 4> DrawList; + typedef SkTLList<Draw, 4> DrawList; + PendingPathRange fPathRange; DrawList fDraws; int fTotalPathCount; - SkMatrix fLocalMatrix; + SkScalar fScale; typedef GrDrawPathBatchBase INHERITED; }; |