aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/GrStencilAndCoverTextContext.cpp68
-rw-r--r--src/gpu/GrStencilAndCoverTextContext.h8
-rw-r--r--src/gpu/batches/GrDrawPathBatch.cpp188
-rw-r--r--src/gpu/batches/GrDrawPathBatch.h149
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;
};