1af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt/*
2af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * Copyright 2015 Google Inc.
3af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt *
4af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * Use of this source code is governed by a BSD-style license that can be
5af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt * found in the LICENSE file.
6af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt */
7af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
8af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrInOrderCommandBuilder.h"
9af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
10af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrColor.h"
11af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrInOrderDrawBuffer.h"
12af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "GrTemplates.h"
13af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt#include "SkPoint.h"
14af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
15af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittstatic bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
16af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
17af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
18af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    if (isWinding) {
19af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // Double check that it is in fact winding.
20af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
21af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
22af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
23af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        SkASSERT(!pathStencilSettings.isTwoSided());
24af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    }
25af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    return isWinding;
26af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt}
27af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
28af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd* GrInOrderCommandBuilder::recordDrawBatch(State* state, GrBatch* batch) {
29af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    // Check if there is a Batch Draw we can batch with
30af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    if (!this->cmdBuffer()->empty() &&
31af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        Cmd::kDrawBatch_CmdType == this->cmdBuffer()->back().type()) {
32af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        DrawBatch* previous = static_cast<DrawBatch*>(&this->cmdBuffer()->back());
33af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
34af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            return NULL;
35af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        }
36af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    }
37af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
38af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    return GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawBatch, (state, batch,
39af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                                                    this->batchTarget()));
40af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt}
41af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
42af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd*
43af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrInOrderCommandBuilder::recordStencilPath(const GrPipelineBuilder& pipelineBuilder,
44af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                           const GrPathProcessor* pathProc,
45af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                           const GrPath* path,
46af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                           const GrScissorState& scissorState,
47af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                           const GrStencilSettings& stencilSettings) {
48af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    StencilPath* sp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), StencilPath,
49af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                               (path, pipelineBuilder.getRenderTarget()));
50af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
51af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    sp->fScissor = scissorState;
52af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    sp->fUseHWAA = pipelineBuilder.isHWAntialias();
53af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    sp->fViewMatrix = pathProc->viewMatrix();
54af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    sp->fStencil = stencilSettings;
55af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    return sp;
56af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt}
57af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
58af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd*
59af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrInOrderCommandBuilder::recordDrawPath(State* state,
60af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                        const GrPathProcessor* pathProc,
61af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                        const GrPath* path,
62af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                        const GrStencilSettings& stencilSettings) {
63af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    DrawPath* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPath, (state, path));
64af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fStencilSettings = stencilSettings;
65af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    return dp;
66af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt}
67af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
68af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrTargetCommands::Cmd*
69af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualittGrInOrderCommandBuilder::recordDrawPaths(State* state,
70af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         GrInOrderDrawBuffer* iodb,
71af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         const GrPathProcessor* pathProc,
72af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         const GrPathRange* pathRange,
73af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         const void* indexValues,
74af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         GrDrawTarget::PathIndexType indexType,
75af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         const float transformValues[],
76af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         GrDrawTarget::PathTransformType transformType,
77af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         int count,
78af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         const GrStencilSettings& stencilSettings,
79af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                         const GrDrawTarget::PipelineInfo& pipelineInfo) {
80af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    SkASSERT(pathRange);
81af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    SkASSERT(indexValues);
82af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    SkASSERT(transformValues);
83af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
84af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    char* savedIndices;
85af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    float* savedTransforms;
86af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
87af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    iodb->appendIndicesAndTransforms(indexValues, indexType,
88af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                     transformValues, transformType,
89af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                                     count, &savedIndices, &savedTransforms);
90af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
91af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    if (!this->cmdBuffer()->empty() &&
92af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        Cmd::kDrawPaths_CmdType == this->cmdBuffer()->back().type()) {
93af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // The previous command was also DrawPaths. Try to collapse this call into the one
94af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // before. Note that stenciling all the paths at once, then covering, may not be
95af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // equivalent to two separate draw calls if there is overlap. Blending won't work,
96af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // and the combined calls may also cancel each other's winding numbers in some
97af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // places. For now the winding numbers are only an issue if the fill is even/odd,
98af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // because DrawPaths is currently only used for glyphs, and glyphs in the same
99af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        // font tend to all wind in the same direction.
100af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        DrawPaths* previous = static_cast<DrawPaths*>(&this->cmdBuffer()->back());
101af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        if (pathRange == previous->pathRange() &&
102af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            indexType == previous->fIndexType &&
103af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            transformType == previous->fTransformType &&
104af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            stencilSettings == previous->fStencilSettings &&
105af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            path_fill_type_is_winding(stencilSettings) &&
106af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            !pipelineInfo.willBlendWithDst(pathProc) &&
107af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt            previous->fState == state) {
108af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
109af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                const int xformSize = GrPathRendering::PathTransformSize(transformType);
110af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
111af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                    (0 == xformSize ||
112af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                     &previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
113af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                    // Fold this DrawPaths call into the one previous.
114af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                    previous->fCount += count;
115af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                    return NULL;
116af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt                }
117af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt        }
118af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    }
119af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt
120af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPaths, (state, pathRange));
121af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fIndices = savedIndices;
122af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fIndexType = indexType;
123af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fTransforms = savedTransforms;
124af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fTransformType = transformType;
125af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fCount = count;
126af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    dp->fStencilSettings = stencilSettings;
127af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt    return dp;
128af242958a5daced0956d7bb3277716b8f0aeaf4bjoshualitt}
129