11fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon/*
21fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon * Copyright 2015 Google Inc.
31fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon *
41fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon * Use of this source code is governed by a BSD-style license that can be
51fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon * found in the LICENSE file.
61fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon */
71fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
882c263f6e4452227334c349430f85ea662962a2bBrian Salomon#include "GrDrawPathOp.h"
954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon#include "GrAppliedClip.h"
1054d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon#include "GrRenderTargetContext.h"
11193d9cf8f2280cd4f8e509c6f3af6b47cea04935cdalton#include "GrRenderTargetPriv.h"
1254d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon#include "SkTemplates.h"
13193d9cf8f2280cd4f8e509c6f3af6b47cea04935cdalton
1454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian SalomonGrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
1548d1b4c2b2c0f41a10376ed657cde043d8f11979Brian Salomon                                   GrPathRendering::FillType fill, GrAAType aaType)
1654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        : INHERITED(classID)
1754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        , fViewMatrix(viewMatrix)
1848d1b4c2b2c0f41a10376ed657cde043d8f11979Brian Salomon        , fInputColor(paint.getColor())
1954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        , fFillType(fill)
20611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon        , fAAType(aaType)
21611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon        , fPipelineSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
22611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon        , fProcessorSet(std::move(paint)) {}
23193d9cf8f2280cd4f8e509c6f3af6b47cea04935cdalton
2482c263f6e4452227334c349430f85ea662962a2bBrian SalomonSkString GrDrawPathOp::dumpInfo() const {
251fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    SkString string;
261dc172165b8186950fda4a269bd1b12c11947b14stephana    string.printf("PATH: 0x%p", fPath.get());
2744fbc79e069c28103a44387d11c62e049ef2967drobertphillips    string.append(INHERITED::dumpInfo());
281fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    return string;
291fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon}
301fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
31e7d30484ea8a5677a9403ccd23a9c0961df62ccdBrian Salomonvoid GrDrawPathOpBase::initPipeline(const GrOpFlushState& state, GrPipeline* pipeline) {
3254d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    static constexpr GrUserStencilSettings kCoverPass{
3354d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon            GrUserStencilSettings::StaticInit<
3454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                    0x0000,
3554d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                    GrUserStencilTest::kNotEqual,
3654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                    0xffff,
3754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                    GrUserStencilOp::kZero,
3854d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                    GrUserStencilOp::kKeep,
3954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                    0xffff>()
4054d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    };
4154d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    GrPipeline::InitArgs args;
4254d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    args.fProcessors = &this->processors();
43611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon    args.fFlags = fPipelineSRGBFlags;
44611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon    if (GrAATypeIsHW(fAAType)) {
45611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon        args.fFlags |= GrPipeline::kHWAntialias_Flag;
46611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon    }
4754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    args.fUserStencil = &kCoverPass;
4854d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    args.fAppliedClip = state.drawOpArgs().fAppliedClip;
4954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    args.fRenderTarget = state.drawOpArgs().fRenderTarget;
5054d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    args.fCaps = &state.caps();
519bee2e5894bb8dd374392f238bc429e16f239583Robert Phillips    args.fResourceProvider = state.resourceProvider();
52bb581ce30f55360fd3a12e7f5aa1fe324b16d085Robert Phillips    args.fDstProxy = state.drawOpArgs().fDstProxy;
5354d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
5454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    return pipeline->init(args);
5554d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon}
561fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
5754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon//////////////////////////////////////////////////////////////////////////////
5854d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
5954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomonvoid init_stencil_pass_settings(const GrOpFlushState& flushState,
6054d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                                GrPathRendering::FillType fillType, GrStencilSettings* stencil) {
6154d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    const GrAppliedClip* appliedClip = flushState.drawOpArgs().fAppliedClip;
6254d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    bool stencilClip = appliedClip && appliedClip->hasStencilClip();
6354d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    stencil->reset(GrPathRendering::GetStencilPassSettings(fillType), stencilClip,
6454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                   flushState.drawOpArgs().fRenderTarget->renderTargetPriv().numStencilBits());
6554d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon}
6654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
6754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon//////////////////////////////////////////////////////////////////////////////
6854d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
6954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomonvoid GrDrawPathOp::onExecute(GrOpFlushState* state) {
7054d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    GrPipeline pipeline;
71e7d30484ea8a5677a9403ccd23a9c0961df62ccdBrian Salomon    this->initPipeline(*state, &pipeline);
72e7d30484ea8a5677a9403ccd23a9c0961df62ccdBrian Salomon    sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->viewMatrix()));
7354d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
7454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    GrStencilSettings stencil;
7554d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    init_stencil_pass_settings(*state, this->fillType(), &stencil);
7654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    state->gpu()->pathRendering()->drawPath(pipeline, *pathProc, stencil, fPath.get());
77c48af934608bbb65650641f66adb51f2102d4274Brian Salomon}
782bf4b3a97b770811d9e0558dbbfbdb57cfafbdb7Brian Salomon
7954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon//////////////////////////////////////////////////////////////////////////////
8054d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
8182c263f6e4452227334c349430f85ea662962a2bBrian SalomonSkString GrDrawPathRangeOp::dumpInfo() const {
821fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    SkString string;
83cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    string.printf("RANGE: 0x%p COUNTS: [", fPathRange.get());
841fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) {
85cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        string.appendf("%d, ", iter.get()->fInstanceData->count());
861fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
871fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    string.remove(string.size() - 2, 2);
881fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    string.append("]");
8944fbc79e069c28103a44387d11c62e049ef2967drobertphillips    string.append(INHERITED::dumpInfo());
901fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    return string;
911fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon}
921fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
9382c263f6e4452227334c349430f85ea662962a2bBrian SalomonGrDrawPathRangeOp::GrDrawPathRangeOp(const SkMatrix& viewMatrix, SkScalar scale, SkScalar x,
9454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                                     SkScalar y, GrPaint&& paint, GrPathRendering::FillType fill,
9548d1b4c2b2c0f41a10376ed657cde043d8f11979Brian Salomon                                     GrAAType aaType, GrPathRange* range,
9648d1b4c2b2c0f41a10376ed657cde043d8f11979Brian Salomon                                     const InstanceData* instanceData, const SkRect& bounds)
9748d1b4c2b2c0f41a10376ed657cde043d8f11979Brian Salomon        : INHERITED(ClassID(), viewMatrix, std::move(paint), fill, aaType)
9882c263f6e4452227334c349430f85ea662962a2bBrian Salomon        , fPathRange(range)
9982c263f6e4452227334c349430f85ea662962a2bBrian Salomon        , fTotalPathCount(instanceData->count())
10082c263f6e4452227334c349430f85ea662962a2bBrian Salomon        , fScale(scale) {
101cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    fDraws.addToHead()->set(instanceData, x, y);
10288cf17d099085b8085ab11571b5094163dbb2c84bsalomon    this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
1031fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon}
1041fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
10554d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomonstatic void pre_translate_transform_values(const float* xforms,
10654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                                           GrPathRendering::PathTransformType type, int count,
10754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                                           SkScalar x, SkScalar y, float* dst);
10854d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
10982c263f6e4452227334c349430f85ea662962a2bBrian Salomonbool GrDrawPathRangeOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
11082c263f6e4452227334c349430f85ea662962a2bBrian Salomon    GrDrawPathRangeOp* that = t->cast<GrDrawPathRangeOp>();
111cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    if (this->fPathRange.get() != that->fPathRange.get() ||
11282c263f6e4452227334c349430f85ea662962a2bBrian Salomon        this->transformType() != that->transformType() || this->fScale != that->fScale ||
11382c263f6e4452227334c349430f85ea662962a2bBrian Salomon        this->color() != that->color() || !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
1141fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon        return false;
1151fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
11654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    if (this->processors() != that->processors()) {
1171fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon        return false;
1181fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
119611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon    if (this->pipelineSRGBFlags() != that->pipelineSRGBFlags()) {
120611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon        return false;
121611572ce3ef9b477e15471c3f5bacb66260e4913Brian Salomon    }
122cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    switch (fDraws.head()->fInstanceData->transformType()) {
123cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kNone_PathTransformType:
124cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            if (this->fDraws.head()->fX != that->fDraws.head()->fX ||
125cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                this->fDraws.head()->fY != that->fDraws.head()->fY) {
126cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                return false;
127cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
128cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
129cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kTranslateX_PathTransformType:
130cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            if (this->fDraws.head()->fY != that->fDraws.head()->fY) {
131cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                return false;
132cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
133cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
134cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kTranslateY_PathTransformType:
135cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            if (this->fDraws.head()->fX != that->fDraws.head()->fX) {
136cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                return false;
137cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
138cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
13982c263f6e4452227334c349430f85ea662962a2bBrian Salomon        default:
14082c263f6e4452227334c349430f85ea662962a2bBrian Salomon            break;
1411fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
1421fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // TODO: Check some other things here. (winding, opaque, pathProc color, vm, ...)
1431fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // Try to combine this call with the previous DrawPaths. We do this by stenciling all the
1441fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // paths together and then covering them in a single pass. This is not equivalent to two
1451fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // separate draw calls, so we can only do it if there is no blending (no overlap would also
1461fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // work). Note that it's also possible for overlapping paths to cancel each other's winding
1471fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // numbers, and we only partially account for this by not allowing even/odd paths to be
1481fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    // combined. (Glyphs in the same font tend to wind the same direction so it works out OK.)
14954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon
1508ff8d24c83353fc421177886d82202da9ff89234cdalton    if (GrPathRendering::kWinding_FillType != this->fillType() ||
15154d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        GrPathRendering::kWinding_FillType != that->fillType()) {
15254d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        return false;
15354d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    }
154a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon    if (!this->processorAnalysis().canCombineOverlappedStencilAndCover()) {
1551fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon        return false;
1561fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
1571fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    fTotalPathCount += that->fTotalPathCount;
158cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    while (Draw* head = that->fDraws.head()) {
159cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        Draw* draw = fDraws.addToTail();
16018300a3aa7cb6eb55d21bb0450dffa58b6fc062cmtklein        draw->fInstanceData.reset(head->fInstanceData.release());
161cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        draw->fX = head->fX;
162cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        draw->fY = head->fY;
1631fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon        that->fDraws.popHead();
1641fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
16588cf17d099085b8085ab11571b5094163dbb2c84bsalomon    this->joinBounds(*that);
1661fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    return true;
1671fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon}
1681fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
1699e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomonvoid GrDrawPathRangeOp::onExecute(GrOpFlushState* state) {
170cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    const Draw& head = *fDraws.head();
171cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton
172cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    SkMatrix drawMatrix(this->viewMatrix());
173cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    drawMatrix.preScale(fScale, fScale);
174cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    drawMatrix.preTranslate(head.fX, head.fY);
175cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton
176cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    SkMatrix localMatrix;
177cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    localMatrix.setScale(fScale, fScale);
178cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    localMatrix.preTranslate(head.fX, head.fY);
179cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton
18082c263f6e4452227334c349430f85ea662962a2bBrian Salomon    sk_sp<GrPathProcessor> pathProc(
181ecea86af4170a52cda5c64dd187ddbe157a682eeBrian Salomon            GrPathProcessor::Create(this->color(), drawMatrix, localMatrix));
182cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton
18354d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    GrPipeline pipeline;
18454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    this->initPipeline(*state, &pipeline);
18554d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    GrStencilSettings stencil;
18654d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon    init_stencil_pass_settings(*state, this->fillType(), &stencil);
1871fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    if (fDraws.count() == 1) {
188cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        const InstanceData& instances = *head.fInstanceData;
18954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        state->gpu()->pathRendering()->drawPaths(pipeline,
1900e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 *pathProc,
19154d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                                                 stencil,
1920e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 fPathRange.get(),
1930e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 instances.indices(),
194cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                                 GrPathRange::kU16_PathIndexType,
195cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                                 instances.transformValues(),
196cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                                 instances.transformType(),
197cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                                 instances.count());
198cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    } else {
199cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        int floatsPerTransform = GrPathRendering::PathTransformSize(this->transformType());
200cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        SkAutoSTMalloc<4096, float> transformStorage(floatsPerTransform * fTotalPathCount);
201cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        SkAutoSTMalloc<2048, uint16_t> indexStorage(fTotalPathCount);
202cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        int idx = 0;
203cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        for (DrawList::Iter iter(fDraws); iter.get(); iter.next()) {
204cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            const Draw& draw = *iter.get();
205cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            const InstanceData& instances = *draw.fInstanceData;
206cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            memcpy(&indexStorage[idx], instances.indices(), instances.count() * sizeof(uint16_t));
207cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            pre_translate_transform_values(instances.transformValues(), this->transformType(),
20882c263f6e4452227334c349430f85ea662962a2bBrian Salomon                                           instances.count(), draw.fX - head.fX, draw.fY - head.fY,
209cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                           &transformStorage[floatsPerTransform * idx]);
210cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            idx += instances.count();
211cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton
212cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            // TODO: Support mismatched transform types if we start using more types other than 2D.
213cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            SkASSERT(instances.transformType() == this->transformType());
214cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        }
215cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        SkASSERT(idx == fTotalPathCount);
216cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton
21754d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon        state->gpu()->pathRendering()->drawPaths(pipeline,
2180e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 *pathProc,
21954d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon                                                 stencil,
2200e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 fPathRange.get(),
2210e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 indexStorage,
2220e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 GrPathRange::kU16_PathIndexType,
2230e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 transformStorage,
2240e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 this->transformType(),
2250e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                                 fTotalPathCount);
2261fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
227cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton}
2281fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon
229cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdaltoninline void pre_translate_transform_values(const float* xforms,
230cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                           GrPathRendering::PathTransformType type, int count,
231cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                                           SkScalar x, SkScalar y, float* dst) {
232cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    if (0 == x && 0 == y) {
233cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        memcpy(dst, xforms, count * GrPathRendering::PathTransformSize(type) * sizeof(float));
234cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        return;
235cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    }
236cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton    switch (type) {
237cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kNone_PathTransformType:
238cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            SkFAIL("Cannot pre-translate kNone_PathTransformType.");
239cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
240cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kTranslateX_PathTransformType:
241cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            SkASSERT(0 == y);
242cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            for (int i = 0; i < count; i++) {
243cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i] = xforms[i] + x;
244cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
245cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
246cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kTranslateY_PathTransformType:
247cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            SkASSERT(0 == x);
248cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            for (int i = 0; i < count; i++) {
249cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i] = xforms[i] + y;
250cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
251cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
252cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kTranslate_PathTransformType:
253cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            for (int i = 0; i < 2 * count; i += 2) {
254cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i] = xforms[i] + x;
255cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i + 1] = xforms[i + 1] + y;
256cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
257cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
258cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        case GrPathRendering::kAffine_PathTransformType:
259cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            for (int i = 0; i < 6 * count; i += 6) {
260cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i] = xforms[i];
261cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i + 1] = xforms[i + 1];
262cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i + 2] = xforms[i] * x + xforms[i + 1] * y + xforms[i + 2];
263cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i + 3] = xforms[i + 3];
264cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i + 4] = xforms[i + 4];
265cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton                dst[i + 5] = xforms[i + 3] * x + xforms[i + 4] * y + xforms[i + 5];
266cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            }
267cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
268cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton        default:
269cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            SkFAIL("Unknown transform type.");
270cdd4682f450b98bad71b8cb0772c02e0902aaa0dcdalton            break;
2711fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon    }
2721fcc01c4158bd68c679569e6c7cfbb302d0ce170bsalomon}
273