aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/effects/GrPorterDuffXferProcessor.h6
-rw-r--r--src/gpu/GrPipeline.cpp42
-rw-r--r--src/gpu/GrPipeline.h12
-rw-r--r--src/gpu/batches/GrDrawBatch.h2
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp17
-rw-r--r--src/gpu/gl/GrGLGpu.cpp2
-rw-r--r--src/gpu/gl/GrGLProgram.cpp2
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp2
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp2
9 files changed, 54 insertions, 33 deletions
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index be014a6b04..457c6eabc8 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -21,10 +21,16 @@ public:
void getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
GrXPFactory::InvariantBlendedColor*) const override;
+
+ /** Because src-over is so common we special case it for performance reasons. If this returns
+ null then the SimpleSrcOverXP() below should be used. */
static GrXferProcessor* CreateSrcOverXferProcessor(const GrCaps& caps,
const GrPipelineOptimizations& optimizations,
bool hasMixedSamples,
const GrXferProcessor::DstTexture*);
+ /** This XP implements non-LCD src-over using hw blend with no optimizations. It is returned
+ by reference because it is global and its ref-cnting methods are not thread safe. */
+ static const GrXferProcessor& SimpleSrcOverXP();
static inline void SrcOverInvariantBlendedColor(
GrColor inputColor,
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index 02edd4201e..e1c733a676 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -28,29 +28,30 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args,
builder.hasMixedSamples(),
&args.fDstTexture,
*args.fCaps));
+ if (!xferProcessor) {
+ return nullptr;
+ }
} else {
+ // This may return nullptr in the common case of src-over implemented using hw blending.
xferProcessor.reset(GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
*args.fCaps,
args.fOpts,
builder.hasMixedSamples(),
&args.fDstTexture));
}
-
- if (!xferProcessor) {
- return nullptr;
- }
-
- GrColor overrideColor = GrColor_ILLEGAL;
+ GrColor overrideColor = GrColor_ILLEGAL;
if (args.fOpts.fColorPOI.firstEffectiveProcessorIndex() != 0) {
overrideColor = args.fOpts.fColorPOI.inputColorToFirstEffectiveProccesor();
}
GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags;
- optFlags = xferProcessor->getOptimizations(args.fOpts,
- builder.getStencil().doesWrite(),
- &overrideColor,
- *args.fCaps);
+ const GrXferProcessor* xpForOpts = xferProcessor ? xferProcessor.get() :
+ &GrPorterDuffXPFactory::SimpleSrcOverXP();
+ optFlags = xpForOpts->getOptimizations(args.fOpts,
+ builder.getStencil().doesWrite(),
+ &overrideColor,
+ *args.fCaps);
// When path rendering the stencil settings are not always set on the GrPipelineBuilder
// so we must check the draw type. In cases where we will skip drawing we simply return a
@@ -167,14 +168,12 @@ void GrPipeline::addDependenciesTo(GrRenderTarget* rt) const {
add_dependencies_for_processor(fFragmentProcessors[i].get(), rt);
}
- if (fXferProcessor.get()) {
- const GrXferProcessor* xfer = fXferProcessor.get();
+ const GrXferProcessor& xfer = this->getXferProcessor();
- for (int i = 0; i < xfer->numTextures(); ++i) {
- GrTexture* texture = xfer->textureAccess(i).getTexture();
- SkASSERT(rt->getLastDrawTarget());
- rt->getLastDrawTarget()->addDependency(texture);
- }
+ for (int i = 0; i < xfer.numTextures(); ++i) {
+ GrTexture* texture = xfer.textureAccess(i).getTexture();
+ SkASSERT(rt->getLastDrawTarget());
+ rt->getLastDrawTarget()->addDependency(texture);
}
}
@@ -185,7 +184,7 @@ void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelin
int* firstColorProcessorIdx,
int* firstCoverageProcessorIdx) {
fIgnoresCoverage = SkToBool(flags & GrXferProcessor::kIgnoreCoverage_OptFlag);
- fReadsFragPosition = fXferProcessor->willReadFragmentPosition();
+ fReadsFragPosition = this->getXferProcessor().willReadFragmentPosition();
if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
(flags & GrXferProcessor::kOverrideColor_OptFlag)) {
@@ -221,8 +220,11 @@ bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b,
return false;
}
- if (!a.getXferProcessor()->isEqual(*b.getXferProcessor())) {
- return false;
+ // Most of the time both are nullptr
+ if (a.fXferProcessor.get() || b.fXferProcessor.get()) {
+ if (!a.getXferProcessor().isEqual(b.getXferProcessor())) {
+ return false;
+ }
}
for (int i = 0; i < a.numFragmentProcessors(); i++) {
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index fbfe119ac0..60d0cab1ab 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -103,7 +103,15 @@ public:
}
int numFragmentProcessors() const { return fFragmentProcessors.count(); }
- const GrXferProcessor* getXferProcessor() const { return fXferProcessor.get(); }
+ const GrXferProcessor& getXferProcessor() const {
+ if (fXferProcessor.get()) {
+ return *fXferProcessor.get();
+ } else {
+ // A null xp member means the common src-over case. GrXferProcessor's ref'ing
+ // mechanism is not thread safe so we do not hold a ref on this global.
+ return GrPorterDuffXPFactory::SimpleSrcOverXP();
+ }
+ }
const GrFragmentProcessor& getColorFragmentProcessor(int idx) const {
SkASSERT(idx < this->numColorFragmentProcessors());
@@ -136,7 +144,7 @@ public:
bool snapVerticesToPixelCenters() const { return SkToBool(fFlags & kSnapVertices_Flag); }
GrXferBarrierType xferBarrierType(const GrCaps& caps) const {
- return fXferProcessor->xferBarrierType(fRenderTarget.get(), caps);
+ return this->getXferProcessor().xferBarrierType(fRenderTarget.get(), caps);
}
/**
diff --git a/src/gpu/batches/GrDrawBatch.h b/src/gpu/batches/GrDrawBatch.h
index 9401c67501..4d4209ab40 100644
--- a/src/gpu/batches/GrDrawBatch.h
+++ b/src/gpu/batches/GrDrawBatch.h
@@ -83,7 +83,7 @@ public:
this->pipeline()->getCoverageFragmentProcessor(i).name(),
this->pipeline()->getCoverageFragmentProcessor(i).dumpInfo().c_str());
}
- string.appendf("XP: %s\n", this->pipeline()->getXferProcessor()->name());
+ string.appendf("XP: %s\n", this->pipeline()->getXferProcessor().name());
return string;
}
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 69e77cfc48..11af4b6aa0 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -850,6 +850,12 @@ void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
////////////////////////////////////////////////////////////////////////////////////////////////
// SrcOver Global functions
////////////////////////////////////////////////////////////////////////////////////////////////
+const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() {
+ static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff,
+ kISA_GrBlendCoeff);
+ static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula);
+ return gSrcOverXP;
+}
GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
const GrCaps& caps,
@@ -860,12 +866,11 @@ GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor(
!(optimizations.fCoveragePOI.isSolidWhite() &&
!hasMixedSamples &&
optimizations.fColorPOI.isOpaque())) {
- static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff,
- kISA_GrBlendCoeff);
- static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula);
- SkASSERT(!dstTexture || !dstTexture->texture());
- gSrcOverXP.ref();
- return &gSrcOverXP;
+ // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP".
+ // We don't simply return the address of that XP here because our caller would have to unref
+ // it and since it is a global object and GrProgramElement's ref-cnting system is not thread
+ // safe.
+ return nullptr;
}
BlendFormula blendFormula;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 32242c5015..f5c646c86f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1495,7 +1495,7 @@ void GrGLGpu::flushScissor(const GrScissorState& scissorState,
bool GrGLGpu::flushGLState(const DrawArgs& args) {
GrXferProcessor::BlendInfo blendInfo;
const GrPipeline& pipeline = *args.fPipeline;
- args.fPipeline->getXferProcessor()->getBlendInfo(&blendInfo);
+ args.fPipeline->getXferProcessor().getBlendInfo(&blendInfo);
this->flushColorWrite(blendInfo.fWriteColor);
this->flushDrawFace(pipeline.getDrawFace());
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 3cf9e4dd7c..c1f5b37b07 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -89,7 +89,7 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc,
this->setFragmentData(primProc, pipeline, textureBindings);
- const GrXferProcessor& xp = *pipeline.getXferProcessor();
+ const GrXferProcessor& xp = pipeline.getXferProcessor();
fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
append_texture_bindings(fXferProcessor.get(), xp, textureBindings);
}
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index e3d292c062..81f92eb243 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -125,7 +125,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
}
}
- const GrXferProcessor& xp = *pipeline.getXferProcessor();
+ const GrXferProcessor& xp = pipeline.getXferProcessor();
xp.getGLSLProcessorKey(*gpu->glCaps().glslCaps(), &b);
//**** use glslCaps here?
if (!gen_meta_key(xp, gpu->glCaps(), 0, &b)) {
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index dc9393db07..97fcce59b7 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -93,7 +93,7 @@ bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr
this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor);
this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs,
inputCoverage);
- this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage,
+ this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage,
this->pipeline().ignoresCoverage());
return true;
}