blob: 1d8aa4f2b4f9baa9b21496272dfac6b7f04c85f7 [file] [log] [blame]
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrPipelineBuilder.h"
#include "GrBatch.h"
#include "GrBlend.h"
#include "GrPaint.h"
#include "GrPipeline.h"
#include "GrProcOptInfo.h"
#include "GrXferProcessor.h"
#include "effects/GrPorterDuffXferProcessor.h"
GrPipelineBuilder::GrPipelineBuilder()
: fFlagBits(0x0)
, fDrawFace(kBoth_DrawFace)
, fColorProcInfoValid(false)
, fCoverageProcInfoValid(false)
, fColorCache(GrColor_ILLEGAL)
, fCoverageCache(GrColor_ILLEGAL) {
SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
}
GrPipelineBuilder& GrPipelineBuilder::operator=(const GrPipelineBuilder& that) {
fRenderTarget.reset(SkSafeRef(that.fRenderTarget.get()));
fFlagBits = that.fFlagBits;
fStencilSettings = that.fStencilSettings;
fDrawFace = that.fDrawFace;
fXPFactory.reset(SkRef(that.getXPFactory()));
fColorStages = that.fColorStages;
fCoverageStages = that.fCoverageStages;
fClip = that.fClip;
fColorProcInfoValid = that.fColorProcInfoValid;
fCoverageProcInfoValid = that.fCoverageProcInfoValid;
fColorCache = that.fColorCache;
fCoverageCache = that.fCoverageCache;
if (fColorProcInfoValid) {
fColorProcInfo = that.fColorProcInfo;
}
if (fCoverageProcInfoValid) {
fCoverageProcInfo = that.fCoverageProcInfo;
}
return *this;
}
void GrPipelineBuilder::setFromPaint(const GrPaint& paint, GrRenderTarget* rt, const GrClip& clip) {
SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numFragmentStages());
fColorStages.reset();
fCoverageStages.reset();
for (int i = 0; i < paint.numColorStages(); ++i) {
fColorStages.push_back(paint.getColorStage(i));
}
for (int i = 0; i < paint.numCoverageStages(); ++i) {
fCoverageStages.push_back(paint.getCoverageStage(i));
}
fXPFactory.reset(SkRef(paint.getXPFactory()));
this->setRenderTarget(rt);
// These have no equivalent in GrPaint, set them to defaults
fDrawFace = kBoth_DrawFace;
fStencilSettings.setDisabled();
fFlagBits = 0;
fClip = clip;
this->setState(GrPipelineBuilder::kDither_StateBit, paint.isDither());
this->setState(GrPipelineBuilder::kHWAntialias_StateBit,
rt->isMultisampled() && paint.isAntiAlias());
fColorProcInfoValid = false;
fCoverageProcInfoValid = false;
fColorCache = GrColor_ILLEGAL;
fCoverageCache = GrColor_ILLEGAL;
}
//////////////////////////////////////////////////////////////////////////////s
bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
return this->getXPFactory()->willNeedDstCopy(caps, colorPOI, coveragePOI);
}
void GrPipelineBuilder::AutoRestoreFragmentProcessors::set(GrPipelineBuilder* pipelineBuilder) {
if (fPipelineBuilder) {
int m = fPipelineBuilder->numColorFragmentStages() - fColorEffectCnt;
SkASSERT(m >= 0);
fPipelineBuilder->fColorStages.pop_back_n(m);
int n = fPipelineBuilder->numCoverageFragmentStages() - fCoverageEffectCnt;
SkASSERT(n >= 0);
fPipelineBuilder->fCoverageStages.pop_back_n(n);
if (m + n > 0) {
fPipelineBuilder->fColorProcInfoValid = false;
fPipelineBuilder->fCoverageProcInfoValid = false;
}
SkDEBUGCODE(--fPipelineBuilder->fBlockEffectRemovalCnt;)
}
fPipelineBuilder = pipelineBuilder;
if (NULL != pipelineBuilder) {
fColorEffectCnt = pipelineBuilder->numColorFragmentStages();
fCoverageEffectCnt = pipelineBuilder->numCoverageFragmentStages();
SkDEBUGCODE(++pipelineBuilder->fBlockEffectRemovalCnt;)
}
}
////////////////////////////////////////////////////////////////////////////////
// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
// others will blend incorrectly.
bool GrPipelineBuilder::canTweakAlphaForCoverage() const {
return this->getXPFactory()->canTweakAlphaForCoverage();
}
////////////////////////////////////////////////////////////////////////////////
GrPipelineBuilder::~GrPipelineBuilder() {
SkASSERT(0 == fBlockEffectRemovalCnt);
}
////////////////////////////////////////////////////////////////////////////////
bool GrPipelineBuilder::willBlendWithDst(const GrPrimitiveProcessor* pp) const {
this->calcColorInvariantOutput(pp);
this->calcCoverageInvariantOutput(pp);
GrXPFactory::InvariantOutput output;
fXPFactory->getInvariantOutput(fColorProcInfo, fCoverageProcInfo, &output);
return output.fWillBlendWithDst;
}
void GrPipelineBuilder::calcColorInvariantOutput(const GrPrimitiveProcessor* pp) const {
fColorProcInfo.calcColorWithPrimProc(pp, fColorStages.begin(), this->numColorFragmentStages());
fColorProcInfoValid = false;
}
void GrPipelineBuilder::calcCoverageInvariantOutput(const GrPrimitiveProcessor* pp) const {
fCoverageProcInfo.calcCoverageWithPrimProc(pp, fCoverageStages.begin(),
this->numCoverageFragmentStages());
fCoverageProcInfoValid = false;
}
void GrPipelineBuilder::calcColorInvariantOutput(const GrBatch* batch) const {
fColorProcInfo.calcColorWithBatch(batch, fColorStages.begin(), this->numColorFragmentStages());
fColorProcInfoValid = false;
}
void GrPipelineBuilder::calcCoverageInvariantOutput(const GrBatch* batch) const {
fCoverageProcInfo.calcCoverageWithBatch(batch, fCoverageStages.begin(),
this->numCoverageFragmentStages());
fCoverageProcInfoValid = false;
}
void GrPipelineBuilder::calcColorInvariantOutput(GrColor color) const {
if (!fColorProcInfoValid || color != fColorCache) {
GrColorComponentFlags flags = kRGBA_GrColorComponentFlags;
fColorProcInfo.calcWithInitialValues(fColorStages.begin(),this->numColorFragmentStages(),
color, flags, false);
fColorProcInfoValid = true;
fColorCache = color;
}
}
void GrPipelineBuilder::calcCoverageInvariantOutput(GrColor coverage) const {
if (!fCoverageProcInfoValid || coverage != fCoverageCache) {
GrColorComponentFlags flags = kRGBA_GrColorComponentFlags;
fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(),
this->numCoverageFragmentStages(), coverage, flags,
true);
fCoverageProcInfoValid = true;
fCoverageCache = coverage;
}
}