Home | History | Annotate | Download | only in gpu
      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 "GrCaps.h"
     11 #include "GrDrawTarget.h"
     12 #include "GrGpu.h"
     13 #include "GrPipelineBuilder.h"
     14 #include "GrProcOptInfo.h"
     15 #include "GrXferProcessor.h"
     16 
     17 #include "batches/GrBatch.h"
     18 
     19 GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
     20                                  GrXPOverridesForBatch* overrides) {
     21     const GrPipelineBuilder& builder = *args.fPipelineBuilder;
     22 
     23     // Create XferProcessor from DS's XPFactory
     24     const GrXPFactory* xpFactory = builder.getXPFactory();
     25     SkAutoTUnref<GrXferProcessor> xferProcessor;
     26     if (xpFactory) {
     27         xferProcessor.reset(xpFactory->createXferProcessor(args.fOpts,
     28                                                            builder.hasMixedSamples(),
     29                                                            &args.fDstTexture,
     30                                                            *args.fCaps));
     31         if (!xferProcessor) {
     32             return nullptr;
     33         }
     34     } else {
     35         // This may return nullptr in the common case of src-over implemented using hw blending.
     36         xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
     37                                                                         *args.fCaps,
     38                                                                         args.fOpts,
     39                                                                         builder.hasMixedSamples(),
     40                                                                         &args.fDstTexture));
     41     }
     42    GrColor overrideColor = GrColor_ILLEGAL;
     43     if (args.fOpts.fColorPOI.firstEffectiveProcessorIndex() != 0) {
     44         overrideColor = args.fOpts.fColorPOI.inputColorToFirstEffectiveProccesor();
     45     }
     46 
     47     GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
     48 
     49     const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
     50                                                        &GrPorterDuffXPFactory::SimpleSrcOverXP();
     51     optFlags = xpForOpts->getOptimizations(args.fOpts,
     52                                            builder.getStencil().doesWrite(),
     53                                            &overrideColor,
     54                                            *args.fCaps);
     55 
     56     // When path rendering the stencil settings are not always set on the GrPipelineBuilder
     57     // so we must check the draw type. In cases where we will skip drawing we simply return a
     58     // null GrPipeline.
     59     if (GrXferProcessor::kSkipDraw_OptFlag & optFlags) {
     60         return nullptr;
     61     }
     62 
     63     // No need to have an override color if it isn't even going to be used.
     64     if (SkToBool(GrXferProcessor::kIgnoreColor_OptFlag & optFlags)) {
     65         overrideColor = GrColor_ILLEGAL;
     66     }
     67 
     68     GrPipeline* pipeline = new (memory) GrPipeline;
     69     pipeline->fXferProcessor.reset(xferProcessor);
     70 
     71     pipeline->fRenderTarget.reset(builder.fRenderTarget.get());
     72     SkASSERT(pipeline->fRenderTarget);
     73     pipeline->fScissorState = *args.fScissor;
     74     pipeline->fStencilSettings = builder.getStencil();
     75     pipeline->fDrawFace = builder.getDrawFace();
     76 
     77     pipeline->fFlags = 0;
     78     if (builder.isHWAntialias()) {
     79         pipeline->fFlags |= kHWAA_Flag;
     80     }
     81     if (builder.snapVerticesToPixelCenters()) {
     82         pipeline->fFlags |= kSnapVertices_Flag;
     83     }
     84 
     85     int firstColorProcessorIdx = args.fOpts.fColorPOI.firstEffectiveProcessorIndex();
     86 
     87     // TODO: Once we can handle single or four channel input into coverage GrFragmentProcessors
     88     // then we can use GrPipelineBuilder's coverageProcInfo (like color above) to set this initial
     89     // information.
     90     int firstCoverageProcessorIdx = 0;
     91 
     92     pipeline->adjustProgramFromOptimizations(builder, optFlags, args.fOpts.fColorPOI,
     93                                              args.fOpts.fCoveragePOI, &firstColorProcessorIdx,
     94                                              &firstCoverageProcessorIdx);
     95 
     96     bool usesLocalCoords = false;
     97 
     98     // Copy GrFragmentProcessors from GrPipelineBuilder to Pipeline
     99     pipeline->fNumColorProcessors = builder.numColorFragmentProcessors() - firstColorProcessorIdx;
    100     int numTotalProcessors = pipeline->fNumColorProcessors +
    101                              builder.numCoverageFragmentProcessors() - firstCoverageProcessorIdx;
    102     pipeline->fFragmentProcessors.reset(numTotalProcessors);
    103     int currFPIdx = 0;
    104     for (int i = firstColorProcessorIdx; i < builder.numColorFragmentProcessors();
    105          ++i, ++currFPIdx) {
    106         const GrFragmentProcessor* fp = builder.getColorFragmentProcessor(i);
    107         pipeline->fFragmentProcessors[currFPIdx].reset(fp);
    108         usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
    109     }
    110 
    111     for (int i = firstCoverageProcessorIdx; i < builder.numCoverageFragmentProcessors();
    112          ++i, ++currFPIdx) {
    113         const GrFragmentProcessor* fp = builder.getCoverageFragmentProcessor(i);
    114         pipeline->fFragmentProcessors[currFPIdx].reset(fp);
    115         usesLocalCoords = usesLocalCoords || fp->usesLocalCoords();
    116     }
    117 
    118     // Setup info we need to pass to GrPrimitiveProcessors that are used with this GrPipeline.
    119     overrides->fFlags = 0;
    120     if (!SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag)) {
    121         overrides->fFlags |= GrXPOverridesForBatch::kReadsColor_Flag;
    122     }
    123     if (GrColor_ILLEGAL != overrideColor) {
    124         overrides->fFlags |= GrXPOverridesForBatch::kUseOverrideColor_Flag;
    125         overrides->fOverrideColor = overrideColor;
    126     }
    127     if (!SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag)) {
    128         overrides->fFlags |= GrXPOverridesForBatch::kReadsCoverage_Flag;
    129     }
    130     if (usesLocalCoords) {
    131         overrides->fFlags |= GrXPOverridesForBatch::kReadsLocalCoords_Flag;
    132     }
    133     if (SkToBool(optFlags & GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag)) {
    134         overrides->fFlags |= GrXPOverridesForBatch::kCanTweakAlphaForCoverage_Flag;
    135     }
    136 
    137     GrXPFactory::InvariantBlendedColor blendedColor;
    138     if (xpFactory) {
    139         xpFactory->getInvariantBlendedColor(args.fOpts.fColorPOI, &blendedColor);
    140     } else {
    141         GrPorterDuffXPFactory::SrcOverInvariantBlendedColor(args.fOpts.fColorPOI.color(),
    142                                                             args.fOpts.fColorPOI.validFlags(),
    143                                                             args.fOpts.fColorPOI.isOpaque(),
    144                                                             &blendedColor);
    145     }
    146     if (blendedColor.fWillBlendWithDst) {
    147         overrides->fFlags |= GrXPOverridesForBatch::kWillColorBlendWithDst_Flag;
    148     }
    149 
    150     return pipeline;
    151 }
    152 
    153 static void add_dependencies_for_processor(const GrFragmentProcessor* proc, GrRenderTarget* rt) {
    154     for (int i = 0; i < proc->numChildProcessors(); ++i) {
    155         // need to recurse
    156         add_dependencies_for_processor(&proc->childProcessor(i), rt);
    157     }
    158 
    159     for (int i = 0; i < proc->numTextures(); ++i) {
    160         GrTexture* texture = proc->textureAccess(i).getTexture();
    161         SkASSERT(rt->getLastDrawTarget());
    162         rt->getLastDrawTarget()->addDependency(texture);
    163     }
    164 }
    165 
    166 void GrPipeline::addDependenciesTo(GrRenderTarget* rt) const {
    167     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
    168         add_dependencies_for_processor(fFragmentProcessors[i].get(), rt);
    169     }
    170 
    171     const GrXferProcessor& xfer = this->getXferProcessor();
    172 
    173     for (int i = 0; i < xfer.numTextures(); ++i) {
    174         GrTexture* texture = xfer.textureAccess(i).getTexture();
    175         SkASSERT(rt->getLastDrawTarget());
    176         rt->getLastDrawTarget()->addDependency(texture);
    177     }
    178 }
    179 
    180 void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelineBuilder,
    181                                                 GrXferProcessor::OptFlags flags,
    182                                                 const GrProcOptInfo& colorPOI,
    183                                                 const GrProcOptInfo& coveragePOI,
    184                                                 int* firstColorProcessorIdx,
    185                                                 int* firstCoverageProcessorIdx) {
    186     fIgnoresCoverage = SkToBool(flags & GrXferProcessor::kIgnoreCoverage_OptFlag);
    187     fReadsFragPosition = this->getXferProcessor().willReadFragmentPosition();
    188 
    189     if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
    190         (flags & GrXferProcessor::kOverrideColor_OptFlag)) {
    191         *firstColorProcessorIdx = pipelineBuilder.numColorFragmentProcessors();
    192     } else {
    193         if (colorPOI.readsFragPosition()) {
    194             fReadsFragPosition = true;
    195         }
    196     }
    197 
    198     if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
    199         *firstCoverageProcessorIdx = pipelineBuilder.numCoverageFragmentProcessors();
    200     } else {
    201         if (coveragePOI.readsFragPosition()) {
    202             fReadsFragPosition = true;
    203         }
    204     }
    205 }
    206 
    207 ////////////////////////////////////////////////////////////////////////////////
    208 
    209 bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b,
    210                           bool ignoreCoordTransforms) {
    211     SkASSERT(&a != &b);
    212 
    213     if (a.getRenderTarget() != b.getRenderTarget() ||
    214         a.fFragmentProcessors.count() != b.fFragmentProcessors.count() ||
    215         a.fNumColorProcessors != b.fNumColorProcessors ||
    216         a.fScissorState != b.fScissorState ||
    217         a.fFlags != b.fFlags ||
    218         a.fStencilSettings != b.fStencilSettings ||
    219         a.fDrawFace != b.fDrawFace) {
    220         return false;
    221     }
    222 
    223     // Most of the time both are nullptr
    224     if (a.fXferProcessor.get() || b.fXferProcessor.get()) {
    225         if (!a.getXferProcessor().isEqual(b.getXferProcessor())) {
    226             return false;
    227         }
    228     }
    229 
    230     for (int i = 0; i < a.numFragmentProcessors(); i++) {
    231         if (!a.getFragmentProcessor(i).isEqual(b.getFragmentProcessor(i), ignoreCoordTransforms)) {
    232             return false;
    233         }
    234     }
    235     return true;
    236 }
    237 
    238