Index: src/gpu/batches/GrDrawPathBatch.cpp |
diff --git a/src/gpu/batches/GrDrawPathBatch.cpp b/src/gpu/batches/GrDrawPathBatch.cpp |
index c2007ce933b7399cf4e9ab55307d7615e87da0cd..3264c0fbafe49f84a56dfc8d6fdb89082c6d11a6 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); |
} |