1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrPipeline.h"
9
10#include "GrBatch.h"
11#include "GrDrawTargetCaps.h"
12#include "GrGpu.h"
13#include "GrPipelineBuilder.h"
14#include "GrProcOptInfo.h"
15#include "GrXferProcessor.h"
16
17GrPipeline::GrPipeline(const GrPipelineBuilder& pipelineBuilder,
18                       const GrProcOptInfo& colorPOI,
19                       const GrProcOptInfo& coveragePOI,
20                       const GrDrawTargetCaps& caps,
21                       const GrScissorState& scissorState,
22                       const GrDeviceCoordTexture* dstCopy) {
23    // Create XferProcessor from DS's XPFactory
24    SkAutoTUnref<GrXferProcessor> xferProcessor(
25        pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI, dstCopy, caps));
26
27    GrColor overrideColor = GrColor_ILLEGAL;
28    if (colorPOI.firstEffectiveStageIndex() != 0) {
29        overrideColor = colorPOI.inputColorToEffectiveStage();
30    }
31
32    GrXferProcessor::OptFlags optFlags;
33    if (xferProcessor) {
34        fXferProcessor.reset(xferProcessor.get());
35
36        optFlags = xferProcessor->getOptimizations(colorPOI,
37                                                   coveragePOI,
38                                                   pipelineBuilder.getStencil().doesWrite(),
39                                                   &overrideColor,
40                                                   caps);
41    }
42
43    // When path rendering the stencil settings are not always set on the GrPipelineBuilder
44    // so we must check the draw type. In cases where we will skip drawing we simply return a
45    // null GrPipeline.
46    if (!xferProcessor || (GrXferProcessor::kSkipDraw_OptFlag & optFlags)) {
47        // Set the fields that don't default init and return. The lack of a render target will
48        // indicate that this can be skipped.
49        fFlags = 0;
50        fDrawFace = GrPipelineBuilder::kInvalid_DrawFace;
51        return;
52    }
53
54    fRenderTarget.reset(pipelineBuilder.fRenderTarget.get());
55    SkASSERT(fRenderTarget);
56    fScissorState = scissorState;
57    fStencilSettings = pipelineBuilder.getStencil();
58    fDrawFace = pipelineBuilder.getDrawFace();
59
60    fFlags = 0;
61    if (pipelineBuilder.isHWAntialias()) {
62        fFlags |= kHWAA_Flag;
63    }
64    if (pipelineBuilder.isDither()) {
65        fFlags |= kDither_Flag;
66    }
67    if (pipelineBuilder.snapVerticesToPixelCenters()) {
68        fFlags |= kSnapVertices_Flag;
69    }
70
71    int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
72
73    // TODO: Once we can handle single or four channel input into coverage stages then we can use
74    // GrPipelineBuilder's coverageProcInfo (like color above) to set this initial information.
75    int firstCoverageStageIdx = 0;
76
77    this->adjustProgramFromOptimizations(pipelineBuilder, optFlags, colorPOI, coveragePOI,
78                                         &firstColorStageIdx, &firstCoverageStageIdx);
79
80    bool usesLocalCoords = false;
81
82    // Copy Stages from PipelineBuilder to Pipeline
83    for (int i = firstColorStageIdx; i < pipelineBuilder.numColorFragmentStages(); ++i) {
84        SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
85                               GrPendingFragmentStage,
86                               (pipelineBuilder.fColorStages[i]));
87        usesLocalCoords = usesLocalCoords ||
88                          pipelineBuilder.fColorStages[i].processor()->usesLocalCoords();
89    }
90
91    fNumColorStages = fFragmentStages.count();
92    for (int i = firstCoverageStageIdx; i < pipelineBuilder.numCoverageFragmentStages(); ++i) {
93        SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
94                               GrPendingFragmentStage,
95                               (pipelineBuilder.fCoverageStages[i]));
96        usesLocalCoords = usesLocalCoords ||
97                          pipelineBuilder.fCoverageStages[i].processor()->usesLocalCoords();
98    }
99
100    // let the GP init the batch tracker
101    fInitBT.fColorIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag);
102    fInitBT.fOverrideColor = fInitBT.fColorIgnored ? GrColor_ILLEGAL : overrideColor;
103    fInitBT.fCoverageIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag);
104    fInitBT.fUsesLocalCoords = usesLocalCoords;
105    fInitBT.fCanTweakAlphaForCoverage =
106        SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag);
107}
108
109void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelineBuilder,
110                                                GrXferProcessor::OptFlags flags,
111                                                const GrProcOptInfo& colorPOI,
112                                                const GrProcOptInfo& coveragePOI,
113                                                int* firstColorStageIdx,
114                                                int* firstCoverageStageIdx) {
115    fReadsFragPosition = fXferProcessor->willReadFragmentPosition();
116
117    if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
118        (flags & GrXferProcessor::kOverrideColor_OptFlag)) {
119        *firstColorStageIdx = pipelineBuilder.numColorFragmentStages();
120    } else {
121        if (coveragePOI.readsFragPosition()) {
122            fReadsFragPosition = true;
123        }
124    }
125
126    if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
127        *firstCoverageStageIdx = pipelineBuilder.numCoverageFragmentStages();
128    } else {
129        if (coveragePOI.readsFragPosition()) {
130            fReadsFragPosition = true;
131        }
132    }
133}
134
135////////////////////////////////////////////////////////////////////////////////
136
137bool GrPipeline::isEqual(const GrPipeline& that) const {
138    if (this->getRenderTarget() != that.getRenderTarget() ||
139        this->fFragmentStages.count() != that.fFragmentStages.count() ||
140        this->fNumColorStages != that.fNumColorStages ||
141        this->fScissorState != that.fScissorState ||
142        this->fFlags != that.fFlags ||
143        this->fStencilSettings != that.fStencilSettings ||
144        this->fDrawFace != that.fDrawFace) {
145        return false;
146    }
147
148    if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) {
149        return false;
150    }
151
152    // The program desc comparison should have already assured that the stage counts match.
153    SkASSERT(this->numFragmentStages() == that.numFragmentStages());
154    for (int i = 0; i < this->numFragmentStages(); i++) {
155
156        if (this->getFragmentStage(i) != that.getFragmentStage(i)) {
157            return false;
158        }
159    }
160    return true;
161}
162
163