aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-02-04 06:14:22 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-02-04 06:14:22 -0800
commit3e9dfdb3784c0cbfecf7589a74aa9aff7ef40abd (patch)
tree8c92e754fbf5da2879845543632987c52479735e /src
parent3b7f7b092c8233a651248da8f23e1cfc85ac829b (diff)
Revert "Move DstCopy on gpu into the GrXferProcessor."
This reverts commit 74a11753604768bf461b80cabb66060e8564d82c. TBR=joshualitt@google.com,bsalomon@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Review URL: https://codereview.chromium.org/896163003
Diffstat (limited to 'src')
-rw-r--r--src/effects/SkArithmeticMode_gpu.cpp31
-rw-r--r--src/effects/SkArithmeticMode_gpu.h31
-rw-r--r--src/gpu/GrBatchTarget.cpp6
-rw-r--r--src/gpu/GrDrawTarget.cpp57
-rw-r--r--src/gpu/GrDrawTarget.h11
-rw-r--r--src/gpu/GrGpu.h1
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp34
-rw-r--r--src/gpu/GrInOrderDrawBuffer.h13
-rw-r--r--src/gpu/GrPipeline.cpp17
-rw-r--r--src/gpu/GrPipeline.h7
-rw-r--r--src/gpu/GrPipelineBuilder.cpp4
-rw-r--r--src/gpu/GrPipelineBuilder.h5
-rw-r--r--src/gpu/GrProgramDesc.h17
-rw-r--r--src/gpu/GrTest.cpp1
-rw-r--r--src/gpu/GrXferProcessor.cpp55
-rw-r--r--src/gpu/effects/GrCoverageSetOpXP.cpp28
-rw-r--r--src/gpu/effects/GrCoverageSetOpXP.h15
-rw-r--r--src/gpu/effects/GrCustomXfermode.cpp28
-rw-r--r--src/gpu/effects/GrCustomXfermodePriv.h27
-rw-r--r--src/gpu/effects/GrDisableColorXP.cpp18
-rw-r--r--src/gpu/effects/GrDisableColorXP.h15
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp47
-rw-r--r--src/gpu/gl/GrGLGpu.cpp4
-rw-r--r--src/gpu/gl/GrGLGpu.h1
-rw-r--r--src/gpu/gl/GrGLProgram.cpp35
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp17
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h3
-rw-r--r--src/gpu/gl/GrGLXferProcessor.cpp61
-rw-r--r--src/gpu/gl/GrGLXferProcessor.h18
-rw-r--r--src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp51
-rw-r--r--src/gpu/gl/builders/GrGLFragmentShaderBuilder.h1
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp6
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h5
33 files changed, 341 insertions, 329 deletions
diff --git a/src/effects/SkArithmeticMode_gpu.cpp b/src/effects/SkArithmeticMode_gpu.cpp
index 8022d668b4..48b7bcd610 100644
--- a/src/effects/SkArithmeticMode_gpu.cpp
+++ b/src/effects/SkArithmeticMode_gpu.cpp
@@ -166,15 +166,7 @@ public:
~GLArithmeticXP() SK_OVERRIDE {}
- static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) {
- const GrArithmeticXP& arith = processor.cast<GrArithmeticXP>();
- uint32_t key = arith.enforcePMColor() ? 1 : 0;
- b->add32(key);
- }
-
-private:
- void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
const char* dstColor = fsBuilder->dstColor();
@@ -192,13 +184,21 @@ private:
args.fInputCoverage, dstColor);
}
- void onSetData(const GrGLProgramDataManager& pdman,
- const GrXferProcessor& processor) SK_OVERRIDE {
+ void setData(const GrGLProgramDataManager& pdman,
+ const GrXferProcessor& processor) SK_OVERRIDE {
const GrArithmeticXP& arith = processor.cast<GrArithmeticXP>();
pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
fEnforcePMColor = arith.enforcePMColor();
};
+ static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) {
+ const GrArithmeticXP& arith = processor.cast<GrArithmeticXP>();
+ uint32_t key = arith.enforcePMColor() ? 1 : 0;
+ b->add32(key);
+ }
+
+private:
GrGLProgramDataManager::UniformHandle fKUni;
bool fEnforcePMColor;
@@ -207,18 +207,17 @@ private:
///////////////////////////////////////////////////////////////////////////////
-GrArithmeticXP::GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor,
- const GrDeviceCoordTexture* dstCopy, bool willReadDstColor)
- : INHERITED(dstCopy, willReadDstColor)
- , fK1(k1)
+GrArithmeticXP::GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor)
+ : fK1(k1)
, fK2(k2)
, fK3(k3)
, fK4(k4)
, fEnforcePMColor(enforcePMColor) {
this->initClassID<GrPorterDuffXferProcessor>();
+ this->setWillReadDstColor();
}
-void GrArithmeticXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
+void GrArithmeticXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
GLArithmeticXP::GenKey(*this, caps, b);
}
diff --git a/src/effects/SkArithmeticMode_gpu.h b/src/effects/SkArithmeticMode_gpu.h
index b282e22427..2998eabc3b 100644
--- a/src/effects/SkArithmeticMode_gpu.h
+++ b/src/effects/SkArithmeticMode_gpu.h
@@ -13,7 +13,6 @@
#if SK_SUPPORT_GPU
#include "GrCoordTransform.h"
-#include "GrDrawTargetCaps.h"
#include "GrFragmentProcessor.h"
#include "GrTextureAccess.h"
#include "GrTypes.h"
@@ -73,17 +72,16 @@ private:
class GrArithmeticXP : public GrXferProcessor {
public:
- static GrXferProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
- const GrDeviceCoordTexture* dstCopy,
- bool willReadDstColor) {
- return SkNEW_ARGS(GrArithmeticXP, (k1, k2, k3, k4, enforcePMColor, dstCopy,
- willReadDstColor));
+ static GrXferProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor) {
+ return SkNEW_ARGS(GrArithmeticXP, (k1, k2, k3, k4, enforcePMColor));
}
~GrArithmeticXP() SK_OVERRIDE {};
const char* name() const SK_OVERRIDE { return "Arithmetic"; }
+ void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
@@ -107,10 +105,7 @@ public:
bool enforcePMColor() const { return fEnforcePMColor; }
private:
- GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor,
- const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
-
- void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+ GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor);
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
const GrArithmeticXP& xp = xpBase.cast<GrArithmeticXP>();
@@ -138,6 +133,11 @@ public:
return SkNEW_ARGS(GrArithmeticXPFactory, (k1, k2, k3, k4, enforcePMColor));
}
+ GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
+ return GrArithmeticXP::Create(fK1, fK2, fK3, fK4, fEnforcePMColor);
+ }
+
bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE {
return true;
}
@@ -154,18 +154,11 @@ public:
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
+ bool willReadDst() const SK_OVERRIDE { return true; }
+
private:
GrArithmeticXPFactory(float k1, float k2, float k3, float k4, bool enforcePMColor);
- GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE {
- return GrArithmeticXP::Create(fK1, fK2, fK3, fK4, fEnforcePMColor, dstCopy,
- this->willReadDstColor());
- }
-
- bool willReadDstColor() const SK_OVERRIDE { return true; }
-
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrArithmeticXPFactory& xpf = xpfBase.cast<GrArithmeticXPFactory>();
if (fK1 != xpf.fK1 ||
diff --git a/src/gpu/GrBatchTarget.cpp b/src/gpu/GrBatchTarget.cpp
index 7a2d14e923..494bc474f8 100644
--- a/src/gpu/GrBatchTarget.cpp
+++ b/src/gpu/GrBatchTarget.cpp
@@ -21,7 +21,8 @@ void GrBatchTarget::flush() {
BufferedFlush* bf = iter.get();
const GrPipeline* pipeline = bf->fPipeline;
const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get();
- fGpu->buildProgramDesc(&desc, *primProc, *pipeline, bf->fBatchTracker);
+ fGpu->buildProgramDesc(&desc, *primProc, *pipeline, pipeline->descInfo(),
+ bf->fBatchTracker);
GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker);
for (int i = 0; i < bf->fDraws.count(); i++) {
@@ -39,7 +40,8 @@ void GrBatchTarget::flushNext(int n) {
BufferedFlush* bf = fIter.get();
const GrPipeline* pipeline = bf->fPipeline;
const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get();
- fGpu->buildProgramDesc(&desc, *primProc, *pipeline, bf->fBatchTracker);
+ fGpu->buildProgramDesc(&desc, *primProc, *pipeline, pipeline->descInfo(),
+ bf->fBatchTracker);
GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker);
for (int i = 0; i < bf->fDraws.count(); i++) {
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index b4cd5a3675..b89d70ea2b 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -384,15 +384,15 @@ bool GrDrawTarget::checkDraw(const GrPipelineBuilder& pipelineBuilder,
return true;
}
-bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
+bool GrDrawTarget::setupDstReadIfNecessary(GrPipelineBuilder* pipelineBuilder,
GrDeviceCoordTexture* dstCopy,
const SkRect* drawBounds) {
- if (!pipelineBuilder.willXPNeedDstCopy(*this->caps())) {
+ if (this->caps()->dstReadInShaderSupport() || !pipelineBuilder->willEffectReadDstColor()) {
return true;
}
SkIRect copyRect;
const GrClipData* clip = this->getClip();
- GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
+ GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
clip->getConservativeBounds(rt, &copyRect);
if (drawBounds) {
@@ -416,9 +416,6 @@ bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuil
this->initCopySurfaceDstDesc(rt, &desc);
desc.fWidth = copyRect.width();
desc.fHeight = copyRect.height();
- // Only xfer processors can use dst copies, and the contract with the XP is that we always
- // supply a copy texture with origin in the top left.
- desc.fOrigin = kTopLeft_GrSurfaceOrigin;
SkAutoTUnref<GrTexture> copy(
fContext->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
@@ -473,9 +470,14 @@ void GrDrawTarget::drawIndexed(GrPipelineBuilder* pipelineBuilder,
info.setDevBounds(*devBounds);
}
+ // TODO: We should continue with incorrect blending.
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
+ return;
+ }
this->setDrawBuffers(&info, gp->getVertexStride());
- this->onDraw(*pipelineBuilder, gp, info, scissorState);
+ this->onDraw(*pipelineBuilder, gp, info, scissorState, dstCopy.texture() ? &dstCopy : NULL);
}
}
@@ -512,9 +514,15 @@ void GrDrawTarget::drawNonIndexed(GrPipelineBuilder* pipelineBuilder,
info.setDevBounds(*devBounds);
}
+ // TODO: We should continue with incorrect blending.
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
+ return;
+ }
+
this->setDrawBuffers(&info, gp->getVertexStride());
- this->onDraw(*pipelineBuilder, gp, info, scissorState);
+ this->onDraw(*pipelineBuilder, gp, info, scissorState, dstCopy.texture() ? &dstCopy : NULL);
}
}
@@ -533,7 +541,12 @@ void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder,
return;
}
- this->onDrawBatch(batch, *pipelineBuilder, scissorState, devBounds);
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
+ return;
+ }
+
+ this->onDrawBatch(batch, *pipelineBuilder, scissorState, dstCopy.texture() ? &dstCopy : NULL);
}
static const GrStencilSettings& winding_path_stencil_settings() {
@@ -623,8 +636,13 @@ void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder,
pipelineBuilder->getRenderTarget()->getStencilBuffer(),
&stencilSettings);
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, &devBounds)) {
+ return;
+ }
+
this->onDrawPath(*pipelineBuilder, pathProc, path, scissorState, stencilSettings,
- &devBounds);
+ dstCopy.texture() ? &dstCopy : NULL);
}
void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
@@ -658,12 +676,18 @@ void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
pipelineBuilder->getRenderTarget()->getStencilBuffer(),
&stencilSettings);
- // Don't compute a bounding box for dst copy texture, we'll opt
+ // Don't compute a bounding box for setupDstReadIfNecessary(), we'll opt
// instead for it to just copy the entire dst. Realistically this is a moot
// point, because any context that supports NV_path_rendering will also
// support NV_blend_equation_advanced.
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, NULL)) {
+ return;
+ }
+
this->onDrawPaths(*pipelineBuilder, pathProc, pathRange, indices, indexType, transformValues,
- transformType, count, scissorState, stencilSettings, NULL);
+ transformType, count, scissorState, stencilSettings,
+ dstCopy.texture() ? &dstCopy : NULL);
}
void GrDrawTarget::clear(const SkIRect* rect,
@@ -769,6 +793,12 @@ void GrDrawTarget::drawIndexedInstances(GrPipelineBuilder* pipelineBuilder,
info.setDevBounds(*devBounds);
}
+ // TODO: We should continue with incorrect blending.
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
+ return;
+ }
+
while (instanceCount) {
info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw);
info.fVertexCount = info.fInstanceCount * verticesPerInstance;
@@ -782,7 +812,8 @@ void GrDrawTarget::drawIndexedInstances(GrPipelineBuilder* pipelineBuilder,
info.fVertexCount,
info.fIndexCount)) {
this->setDrawBuffers(&info, gp->getVertexStride());
- this->onDraw(*pipelineBuilder, gp, info, scissorState);
+ this->onDraw(*pipelineBuilder, gp, info, scissorState,
+ dstCopy.texture() ? &dstCopy : NULL);
}
info.fStartVertex += info.fVertexCount;
instanceCount -= info.fInstanceCount;
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 1b6651716c..18265c8fb7 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -677,7 +677,7 @@ protected:
// Makes a copy of the dst if it is necessary for the draw. Returns false if a copy is required
// but couldn't be made. Otherwise, returns true. This method needs to be protected because it
// needs to be accessed by GLPrograms to setup a correct drawstate
- bool setupDstReadIfNecessary(const GrPipelineBuilder&,
+ bool setupDstReadIfNecessary(GrPipelineBuilder*,
GrDeviceCoordTexture* dstCopy,
const SkRect* drawBounds);
@@ -720,11 +720,12 @@ private:
virtual void onDraw(const GrPipelineBuilder&,
const GrGeometryProcessor*,
const DrawInfo&,
- const GrScissorState&) = 0;
+ const GrScissorState&,
+ const GrDeviceCoordTexture* dstCopy) = 0;
virtual void onDrawBatch(GrBatch*,
const GrPipelineBuilder&,
const GrScissorState&,
- const SkRect* devBounds) = 0;
+ const GrDeviceCoordTexture* dstCopy) = 0;
// TODO copy in order drawbuffer onDrawRect to here
virtual void onDrawRect(GrPipelineBuilder*,
GrColor color,
@@ -743,7 +744,7 @@ private:
const GrPath*,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) = 0;
+ const GrDeviceCoordTexture* dstCopy) = 0;
virtual void onDrawPaths(const GrPipelineBuilder&,
const GrPathProcessor*,
const GrPathRange*,
@@ -754,7 +755,7 @@ private:
int count,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) = 0;
+ const GrDeviceCoordTexture*) = 0;
virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) = 0;
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 8a3c32b7ab..8c458f18e8 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -298,6 +298,7 @@ public:
virtual void buildProgramDesc(GrProgramDesc*,
const GrPrimitiveProcessor&,
const GrPipeline&,
+ const GrProgramDesc::DescInfo&,
const GrBatchTracker&) const = 0;
// Called to determine whether a copySurface call would succeed or not. Derived
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 3e177ed207..e59df80e96 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -247,13 +247,14 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBu
void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
const GrGeometryProcessor* gp,
const DrawInfo& info,
- const GrScissorState& scissorState) {
+ const GrScissorState& scissorState,
+ const GrDeviceCoordTexture* dstCopy) {
SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
// This closeBatch call is required because we may introduce new draws when we setup clip
this->closeBatch();
- if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, info.getDevBounds())) {
+ if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, dstCopy)) {
return;
}
@@ -275,8 +276,8 @@ void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
const GrPipelineBuilder& pipelineBuilder,
const GrScissorState& scissorState,
- const SkRect* devBounds) {
- if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, devBounds)) {
+ const GrDeviceCoordTexture* dstCopy) {
+ if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, dstCopy)) {
return;
}
@@ -315,11 +316,11 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
const GrPath* path,
const GrScissorState& scissorState,
const GrStencilSettings& stencilSettings,
- const SkRect* devBounds) {
+ const GrDeviceCoordTexture* dstCopy) {
this->closeBatch();
// TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
- if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
+ if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
return;
}
DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
@@ -337,14 +338,14 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
int count,
const GrScissorState& scissorState,
const GrStencilSettings& stencilSettings,
- const SkRect* devBounds) {
+ const GrDeviceCoordTexture* dstCopy) {
SkASSERT(pathRange);
SkASSERT(indices);
SkASSERT(transformValues);
this->closeBatch();
- if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
+ if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
return;
}
@@ -488,6 +489,7 @@ void GrInOrderDrawBuffer::onFlush() {
if (ss->fPrimitiveProcessor) {
this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
ss->fPipeline,
+ ss->fPipeline.descInfo(),
ss->fBatchTracker);
}
currentState = ss;
@@ -582,14 +584,10 @@ bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
const GrPrimitiveProcessor* primProc,
const GrScissorState& scissor,
- const SkRect* devBounds) {
- GrDeviceCoordTexture dstCopy;
- if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
- return false;
- }
+ const GrDeviceCoordTexture* dstCopy) {
SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
(pipelineBuilder, primProc, *this->getGpu()->caps(),
- scissor, &dstCopy));
+ scissor, dstCopy));
if (ss->fPipeline.mustSkip()) {
fCmdBuffer.pop_back();
return false;
@@ -614,17 +612,13 @@ bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipe
bool GrInOrderDrawBuffer::recordStateAndShouldDraw(GrBatch* batch,
const GrPipelineBuilder& pipelineBuilder,
const GrScissorState& scissor,
- const SkRect* devBounds) {
- GrDeviceCoordTexture dstCopy;
- if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
- return false;
- }
+ const GrDeviceCoordTexture* dstCopy) {
// TODO this gets much simpler when we have batches everywhere.
// If the previous command is also a set state, then we check to see if it has a Batch. If so,
// and we can make the two batches equal, and we can combine the states, then we make them equal
SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
(batch, pipelineBuilder, *this->getGpu()->caps(), scissor,
- &dstCopy));
+ dstCopy));
if (ss->fPipeline.mustSkip()) {
fCmdBuffer.pop_back();
return false;
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 3d1bd7c43e..bf9237d426 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -233,11 +233,12 @@ private:
void onDraw(const GrPipelineBuilder&,
const GrGeometryProcessor*,
const DrawInfo&,
- const GrScissorState&) SK_OVERRIDE;
+ const GrScissorState&,
+ const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
void onDrawBatch(GrBatch*,
const GrPipelineBuilder&,
const GrScissorState&,
- const SkRect* devBounds) SK_OVERRIDE;
+ const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
void onDrawRect(GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
@@ -255,7 +256,7 @@ private:
const GrPath*,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) SK_OVERRIDE;
+ const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
void onDrawPaths(const GrPipelineBuilder&,
const GrPathProcessor*,
const GrPathRange*,
@@ -266,7 +267,7 @@ private:
int count,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) SK_OVERRIDE;
+ const GrDeviceCoordTexture*) SK_OVERRIDE;
void onClear(const SkIRect* rect,
GrColor color,
bool canIgnoreRect,
@@ -287,11 +288,11 @@ private:
bool SK_WARN_UNUSED_RESULT recordStateAndShouldDraw(const GrPipelineBuilder&,
const GrPrimitiveProcessor*,
const GrScissorState&,
- const SkRect*);
+ const GrDeviceCoordTexture*);
bool SK_WARN_UNUSED_RESULT recordStateAndShouldDraw(GrBatch*,
const GrPipelineBuilder&,
const GrScissorState&,
- const SkRect*);
+ const GrDeviceCoordTexture*);
// We lazily record clip changes in order to skip clips that have no effect.
void recordClipIfNecessary();
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index bd508e9dc1..911169e336 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -48,7 +48,7 @@ void GrPipeline::internalConstructor(const GrPipelineBuilder& pipelineBuilder,
const GrDeviceCoordTexture* dstCopy) {
// Create XferProcessor from DS's XPFactory
SkAutoTUnref<GrXferProcessor> xferProcessor(
- pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI, dstCopy, caps));
+ pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
GrColor overrideColor = GrColor_ILLEGAL;
if (colorPOI.firstEffectiveStageIndex() != 0) {
@@ -82,6 +82,10 @@ void GrPipeline::internalConstructor(const GrPipelineBuilder& pipelineBuilder,
fScissorState = scissorState;
fStencilSettings = pipelineBuilder.getStencil();
fDrawFace = pipelineBuilder.getDrawFace();
+ // TODO move this out of GrPipeline
+ if (dstCopy) {
+ fDstCopy = *dstCopy;
+ }
fFlags = 0;
if (pipelineBuilder.isHWAntialias()) {
@@ -103,6 +107,8 @@ void GrPipeline::internalConstructor(const GrPipelineBuilder& pipelineBuilder,
this->adjustProgramFromOptimizations(pipelineBuilder, optFlags, colorPOI, coveragePOI,
&firstColorStageIdx, &firstCoverageStageIdx);
+ fDescInfo.fReadsDst = fXferProcessor->willReadDstColor();
+
bool usesLocalCoords = false;
// Copy Stages from PipelineBuilder to Pipeline
@@ -136,20 +142,20 @@ void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelin
const GrProcOptInfo& coveragePOI,
int* firstColorStageIdx,
int* firstCoverageStageIdx) {
- fReadsFragPosition = false;
+ fDescInfo.fReadsFragPosition = false;
if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
(flags & GrXferProcessor::kOverrideColor_OptFlag)) {
*firstColorStageIdx = pipelineBuilder.numColorStages();
} else {
- fReadsFragPosition = colorPOI.readsFragPosition();
+ fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
}
if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
*firstCoverageStageIdx = pipelineBuilder.numCoverageStages();
} else {
if (coveragePOI.readsFragPosition()) {
- fReadsFragPosition = true;
+ fDescInfo.fReadsFragPosition = true;
}
}
}
@@ -163,7 +169,8 @@ bool GrPipeline::isEqual(const GrPipeline& that) const {
this->fScissorState != that.fScissorState ||
this->fFlags != that.fFlags ||
this->fStencilSettings != that.fStencilSettings ||
- this->fDrawFace != that.fDrawFace) {
+ this->fDrawFace != that.fDrawFace ||
+ this->fDstCopy.texture() != that.fDstCopy.texture()) {
return false;
}
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 8480c00458..24d0b62795 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -132,7 +132,9 @@ public:
///////////////////////////////////////////////////////////////////////////
- bool readsFragPosition() const { return fReadsFragPosition; }
+ const GrDeviceCoordTexture* getDstCopy() const { return fDstCopy.texture() ? &fDstCopy : NULL; }
+
+ const GrProgramDesc::DescInfo& descInfo() const { return fDescInfo; }
const GrPipelineInfo& getInitBatchTracker() const { return fInitBT; }
@@ -175,10 +177,11 @@ private:
GrScissorState fScissorState;
GrStencilSettings fStencilSettings;
GrPipelineBuilder::DrawFace fDrawFace;
+ GrDeviceCoordTexture fDstCopy;
uint32_t fFlags;
ProgramXferProcessor fXferProcessor;
FragmentStageArray fFragmentStages;
- bool fReadsFragPosition;
+ GrProgramDesc::DescInfo fDescInfo;
GrPipelineInfo fInitBT;
// This function is equivalent to the offset into fFragmentStages where coverage stages begin.
diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp
index 54d357fd23..90aee748c9 100644
--- a/src/gpu/GrPipelineBuilder.cpp
+++ b/src/gpu/GrPipelineBuilder.cpp
@@ -101,8 +101,8 @@ bool GrPipelineBuilder::canUseFracCoveragePrimProc(GrColor color,
//////////////////////////////////////////////////////////////////////////////s
-bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps) const {
- return this->getXPFactory()->willNeedDstCopy(caps);
+bool GrPipelineBuilder::willEffectReadDstColor() const {
+ return this->getXPFactory()->willReadDst();
}
void GrPipelineBuilder::AutoRestoreEffects::set(GrPipelineBuilder* pipelineBuilder) {
diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h
index 5743c39dc5..df9a1c85ee 100644
--- a/src/gpu/GrPipelineBuilder.h
+++ b/src/gpu/GrPipelineBuilder.h
@@ -102,9 +102,10 @@ public:
const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
/**
- * Checks whether the xp will need a copy of the destination to correctly blend.
+ * Checks whether the xp will read the dst pixel color.
+ * TODO: remove when we have dstCpy contained inside of GrXP
*/
- bool willXPNeedDstCopy(const GrDrawTargetCaps& caps) const;
+ bool willEffectReadDstColor() const;
/**
* The xfer processor factory.
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index 66e0e06b8c..e07e116733 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -55,6 +55,9 @@ public:
}
struct KeyHeader {
+ uint8_t fDstReadKey; // set by GrGLShaderBuilder if there
+ // are effects that must read the dst.
+ // Otherwise, 0.
uint8_t fFragPosKey; // set by GrGLShaderBuilder if there are
// effects that read the fragment position.
// Otherwise, 0.
@@ -76,6 +79,20 @@ public:
// This should really only be used internally, base classes should return their own headers
const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
+ // A struct to communicate descriptor information to the program descriptor builder
+ struct DescInfo {
+ bool operator==(const DescInfo& that) const {
+ return fReadsDst == that.fReadsDst &&
+ fReadsFragPosition == that.fReadsFragPosition;
+ }
+ bool operator!=(const DescInfo& that) const { return !(*this == that); };
+
+ // These flags give aggregated info on the processor stages that are used when building
+ // programs.
+ bool fReadsDst;
+ bool fReadsFragPosition;
+ };
+
private:
template<typename T, size_t OFFSET> T* atOffset() {
return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp
index 2f32eb5d4a..05a4a5f956 100644
--- a/src/gpu/GrTest.cpp
+++ b/src/gpu/GrTest.cpp
@@ -142,6 +142,7 @@ public:
size_t rowBytes) const SK_OVERRIDE { return false; }
void buildProgramDesc(GrProgramDesc*,const GrPrimitiveProcessor&,
const GrPipeline&,
+ const GrProgramDesc::DescInfo&,
const GrBatchTracker&) const SK_OVERRIDE {}
void discard(GrRenderTarget*) SK_OVERRIDE {}
diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp
deleted file mode 100644
index 87d5fe65ac..0000000000
--- a/src/gpu/GrXferProcessor.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 "GrXferProcessor.h"
-#include "gl/GrGLCaps.h"
-
-GrXferProcessor::GrXferProcessor() : fWillReadDstColor(false), fDstCopyTextureOffset() {
-}
-
-GrXferProcessor::GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor)
- : fWillReadDstColor(willReadDstColor)
- , fDstCopyTextureOffset() {
- if (dstCopy && dstCopy->texture()) {
- fDstCopy.reset(dstCopy->texture());
- fDstCopyTextureOffset = dstCopy->offset();
- SkASSERT(kTopLeft_GrSurfaceOrigin == fDstCopy.getTexture()->origin());
- this->addTextureAccess(&fDstCopy);
- }
-}
-
-void GrXferProcessor::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
- uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
- b->add32(key);
- this->onGetGLProcessorKey(caps, b);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- const GrDeviceCoordTexture* dstCopy,
- const GrDrawTargetCaps& caps) const {
-#ifdef SK_DEBUG
- if (this->willReadDstColor()) {
- if (!caps.dstReadInShaderSupport()) {
- SkASSERT(dstCopy && dstCopy->texture());
- } else {
- SkASSERT(!dstCopy || !dstCopy->texture());
- }
- } else {
- SkASSERT(!dstCopy || !dstCopy->texture());
-
- }
-#endif
- return this->onCreateXferProcessor(colorPOI, coveragePOI, dstCopy);
-}
-
-bool GrXPFactory::willNeedDstCopy(const GrDrawTargetCaps& caps) const {
- return (this->willReadDstColor() && !caps.dstReadInShaderSupport());
-}
-
diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp
index 7025d20395..fe286f6bf5 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.cpp
+++ b/src/gpu/effects/GrCoverageSetOpXP.cpp
@@ -21,15 +21,7 @@ public:
~GrGLCoverageSetOpXP() SK_OVERRIDE {}
- static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) {
- const GrCoverageSetOpXP& xp = processor.cast<GrCoverageSetOpXP>();
- uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
- b->add32(key);
- };
-
-private:
- void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
const GrCoverageSetOpXP& xp = args.fXP.cast<GrCoverageSetOpXP>();
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
@@ -40,8 +32,16 @@ private:
}
}
- void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
+ void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
+ static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) {
+ const GrCoverageSetOpXP& xp = processor.cast<GrCoverageSetOpXP>();
+ uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
+ b->add32(key);
+ };
+
+private:
typedef GrGLXferProcessor INHERITED;
};
@@ -56,7 +56,7 @@ GrCoverageSetOpXP::GrCoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
GrCoverageSetOpXP::~GrCoverageSetOpXP() {
}
-void GrCoverageSetOpXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
+void GrCoverageSetOpXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
GrGLCoverageSetOpXP::GenKey(*this, caps, b);
}
@@ -179,10 +179,8 @@ GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invert
}
}
-GrXferProcessor*
-GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& covPOI,
- const GrDeviceCoordTexture* dstCopy) const {
+GrXferProcessor* GrCoverageSetOpXPFactory::createXferProcessor(const GrProcOptInfo& /* colorPOI*/,
+ const GrProcOptInfo& covPOI) const {
return GrCoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
}
diff --git a/src/gpu/effects/GrCoverageSetOpXP.h b/src/gpu/effects/GrCoverageSetOpXP.h
index 0bc9e91170..a144f975b7 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.h
+++ b/src/gpu/effects/GrCoverageSetOpXP.h
@@ -29,6 +29,8 @@ public:
const char* name() const SK_OVERRIDE { return "Coverage Set Op"; }
+ void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
@@ -46,8 +48,6 @@ public:
private:
GrCoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
- void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
-
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
const GrCoverageSetOpXP& xp = xpBase.cast<GrCoverageSetOpXP>();
return (fRegionOp == xp.fRegionOp &&
@@ -66,6 +66,9 @@ class GrCoverageSetOpXPFactory : public GrXPFactory {
public:
static GrXPFactory* Create(SkRegion::Op regionOp, bool invertCoverage = false);
+ GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE;
+
bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE {
return true;
}
@@ -80,15 +83,11 @@ public:
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
+ bool willReadDst() const SK_OVERRIDE { return false; }
+
private:
GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
- GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
-
- bool willReadDstColor() const SK_OVERRIDE { return false; }
-
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrCoverageSetOpXPFactory& xpf = xpfBase.cast<GrCoverageSetOpXPFactory>();
return fRegionOp == xpf.fRegionOp;
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index b77bf2fad1..9aa7153109 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -499,15 +499,7 @@ public:
GLCustomXP(const GrXferProcessor&) {}
~GLCustomXP() SK_OVERRIDE {}
- static void GenKey(const GrXferProcessor& proc, const GrGLCaps&, GrProcessorKeyBuilder* b) {
- uint32_t key = proc.numTextures();
- SkASSERT(key <= 1);
- key |= proc.cast<GrCustomXP>().mode() << 1;
- b->add32(key);
- }
-
-private:
- void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
SkXfermode::Mode mode = args.fXP.cast<GrCustomXP>().mode();
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
const char* dstColor = fsBuilder->dstColor();
@@ -519,20 +511,28 @@ private:
args.fInputCoverage, dstColor);
}
- void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
+ void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
+ static void GenKey(const GrXferProcessor& proc, const GrGLCaps&, GrProcessorKeyBuilder* b) {
+ uint32_t key = proc.numTextures();
+ SkASSERT(key <= 1);
+ key |= proc.cast<GrCustomXP>().mode() << 1;
+ b->add32(key);
+ }
+
+private:
typedef GrGLFragmentProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
-GrCustomXP::GrCustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy,
- bool willReadDstColor)
- : INHERITED(dstCopy, willReadDstColor), fMode(mode) {
+GrCustomXP::GrCustomXP(SkXfermode::Mode mode)
+ : fMode(mode) {
this->initClassID<GrCustomXP>();
+ this->setWillReadDstColor();
}
-void GrCustomXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
+void GrCustomXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
GLCustomXP::GenKey(*this, caps, b);
}
diff --git a/src/gpu/effects/GrCustomXfermodePriv.h b/src/gpu/effects/GrCustomXfermodePriv.h
index 681c805ba7..45a9d3005d 100644
--- a/src/gpu/effects/GrCustomXfermodePriv.h
+++ b/src/gpu/effects/GrCustomXfermodePriv.h
@@ -9,7 +9,6 @@
#define GrCustomXfermodePriv_DEFINED
#include "GrCoordTransform.h"
-#include "GrDrawTargetCaps.h"
#include "GrFragmentProcessor.h"
#include "GrTextureAccess.h"
#include "GrXferProcessor.h"
@@ -58,12 +57,11 @@ private:
class GrCustomXP : public GrXferProcessor {
public:
- static GrXferProcessor* Create(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy,
- bool willReadDstColor) {
+ static GrXferProcessor* Create(SkXfermode::Mode mode) {
if (!GrCustomXfermode::IsSupportedMode(mode)) {
return NULL;
} else {
- return SkNEW_ARGS(GrCustomXP, (mode, dstCopy, willReadDstColor));
+ return SkNEW_ARGS(GrCustomXP, (mode));
}
}
@@ -71,6 +69,8 @@ public:
const char* name() const SK_OVERRIDE { return "Custom Xfermode"; }
+ void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
@@ -90,9 +90,7 @@ public:
SkXfermode::Mode mode() const { return fMode; }
private:
- GrCustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
-
- void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+ GrCustomXP(SkXfermode::Mode mode);
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE;
@@ -107,6 +105,11 @@ class GrCustomXPFactory : public GrXPFactory {
public:
GrCustomXPFactory(SkXfermode::Mode mode);
+ GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
+ return GrCustomXP::Create(fMode);
+ }
+
bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE {
return true;
}
@@ -123,15 +126,9 @@ public:
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
-private:
- GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE {
- return GrCustomXP::Create(fMode, dstCopy, this->willReadDstColor());
- }
-
- bool willReadDstColor() const SK_OVERRIDE { return true; }
+ bool willReadDst() const SK_OVERRIDE { return true; }
+private:
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrCustomXPFactory& xpf = xpfBase.cast<GrCustomXPFactory>();
return fMode == xpf.fMode;
diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp
index 83b6d23119..9383385192 100644
--- a/src/gpu/effects/GrDisableColorXP.cpp
+++ b/src/gpu/effects/GrDisableColorXP.cpp
@@ -17,10 +17,7 @@ public:
~GrGLDisableColorXP() SK_OVERRIDE {}
- static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
-
-private:
- void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
// This emit code should be empty. However, on the nexus 6 there is a driver bug where if
// you do not give gl_FragColor a value, the gl context is lost and we end up drawing
// nothing. So this fix just sets the gl_FragColor arbitrarily to 0.
@@ -28,8 +25,11 @@ private:
fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary);
}
- void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
+ void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
+ static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
+
+private:
typedef GrGLXferProcessor INHERITED;
};
@@ -39,7 +39,7 @@ GrDisableColorXP::GrDisableColorXP() {
this->initClassID<GrDisableColorXP>();
}
-void GrDisableColorXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
+void GrDisableColorXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
GrGLDisableColorXP::GenKey(*this, caps, b);
}
@@ -57,10 +57,8 @@ GrDisableColorXPFactory::GrDisableColorXPFactory() {
this->initClassID<GrDisableColorXPFactory>();
}
-GrXferProcessor*
-GrDisableColorXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& covPOI,
- const GrDeviceCoordTexture* dstCopy) const {
+GrXferProcessor* GrDisableColorXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& covPOI) const {
return GrDisableColorXP::Create();
}
diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h
index da6fa4523b..d62c3201dd 100644
--- a/src/gpu/effects/GrDisableColorXP.h
+++ b/src/gpu/effects/GrDisableColorXP.h
@@ -27,6 +27,8 @@ public:
const char* name() const SK_OVERRIDE { return "Disable Color"; }
+ void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
@@ -44,8 +46,6 @@ public:
private:
GrDisableColorXP();
- void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
-
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
return true;
}
@@ -61,6 +61,9 @@ public:
return SkNEW(GrDisableColorXPFactory);
}
+ GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE;
+
bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE {
return true;
}
@@ -78,15 +81,11 @@ public:
output->fWillBlendWithDst = 0;
}
+ bool willReadDst() const SK_OVERRIDE { return false; }
+
private:
GrDisableColorXPFactory();
- GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
-
- bool willReadDstColor() const SK_OVERRIDE { return false; }
-
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
return true;
}
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 320d943392..5038aa333f 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -38,15 +38,7 @@ public:
virtual ~GrGLPorterDuffXferProcessor() {}
- static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) {
- const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferProcessor>();
- b->add32(xp.primaryOutputType());
- b->add32(xp.secondaryOutputType());
- };
-
-private:
- void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProcessor>();
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
if (xp.hasSecondaryOutput()) {
@@ -88,18 +80,23 @@ private:
}
}
- void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
+ void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
+ static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) {
+ const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferProcessor>();
+ b->add32(xp.primaryOutputType());
+ b->add32(xp.secondaryOutputType());
+ };
+
+private:
typedef GrGLXferProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
-GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend,
- GrBlendCoeff dstBlend,
- GrColor constant,
- const GrDeviceCoordTexture* dstCopy,
- bool willReadDstColor)
+GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend,
+ GrColor constant)
: fSrcBlend(srcBlend)
, fDstBlend(dstBlend)
, fBlendConstant(constant)
@@ -111,8 +108,8 @@ GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend,
GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() {
}
-void GrPorterDuffXferProcessor::onGetGLProcessorKey(const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) const {
+void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) const {
GrGLPorterDuffXferProcessor::GenKey(*this, caps, b);
}
@@ -356,20 +353,16 @@ GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) {
}
}
-GrXferProcessor*
-GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& covPOI,
- const GrDeviceCoordTexture* dstCopy) const {
+GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& covPOI) const {
if (!covPOI.isFourChannelOutput()) {
- return GrPorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy,
- this->willReadDstColor());
+ return GrPorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff);
} else {
if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags())) {
SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags());
GrColor blendConstant = GrUnPreMulColor(colorPOI.color());
return GrPorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_GrBlendCoeff,
- blendConstant, dstCopy,
- this->willReadDstColor());
+ blendConstant);
} else {
return NULL;
}
@@ -491,10 +484,6 @@ void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
output->fWillBlendWithDst = false;
}
-bool GrPorterDuffXPFactory::willReadDstColor() const {
- return false;
-}
-
GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 6419aa6b52..dd55abb0a6 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1451,8 +1451,10 @@ void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
void GrGLGpu::buildProgramDesc(GrProgramDesc* desc,
const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
+ const GrProgramDesc::DescInfo& descInfo,
const GrBatchTracker& batchTracker) const {
- if (!GrGLProgramDescBuilder::Build(desc, primProc, pipeline, this, batchTracker)) {
+ if (!GrGLProgramDescBuilder::Build(desc, primProc, pipeline, descInfo, this,
+ batchTracker)) {
SkDEBUGFAIL("Failed to generate GL program descriptor");
}
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 18f0f749c4..7eda014344 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -108,6 +108,7 @@ public:
void buildProgramDesc(GrProgramDesc*,
const GrPrimitiveProcessor&,
const GrPipeline&,
+ const GrProgramDesc::DescInfo&,
const GrBatchTracker&) const SK_OVERRIDE;
private:
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index eebcf6b2f3..ad63dc4ea7 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -61,6 +61,10 @@ void GrGLProgram::abandon() {
void GrGLProgram::initSamplerUniforms() {
GL_CALL(UseProgram(fProgramID));
GrGLint texUnitIdx = 0;
+ if (fBuiltinUniformHandles.fDstCopySamplerUni.isValid()) {
+ fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
+ fDstCopyTexUnit = texUnitIdx++;
+ }
this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
if (fXferProcessor.get()) {
this->initSamplers(fXferProcessor.get(), &texUnitIdx);
@@ -103,15 +107,38 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline
const GrBatchTracker& batchTracker) {
this->setRenderTargetState(primProc, pipeline);
+ const GrDeviceCoordTexture* dstCopy = pipeline.getDstCopy();
+ if (dstCopy) {
+ if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
+ fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni,
+ static_cast<GrGLfloat>(dstCopy->offset().fX),
+ static_cast<GrGLfloat>(dstCopy->offset().fY));
+ fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni,
+ 1.f / dstCopy->texture()->width(),
+ 1.f / dstCopy->texture()->height());
+ GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
+ static GrTextureParams kParams; // the default is clamp, nearest filtering.
+ fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
+ } else {
+ SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
+ SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
+ }
+ } else {
+ SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
+ SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
+ SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
+ }
+
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
fGeometryProcessor->fGLProc->setData(fProgramDataManager, primProc, batchTracker);
this->bindTextures(fGeometryProcessor.get(), primProc);
- const GrXferProcessor& xp = *pipeline.getXferProcessor();
- fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
- this->bindTextures(fXferProcessor.get(), xp);
-
+ if (fXferProcessor.get()) {
+ const GrXferProcessor& xp = *pipeline.getXferProcessor();
+ fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
+ this->bindTextures(fXferProcessor.get(), xp);
+ }
this->setFragmentData(primProc, pipeline);
// Some of GrGLProgram subclasses need to update state here
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index abe2439495..32f831e84c 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -89,6 +89,7 @@ static bool get_meta_key(const GrProcessor& proc,
bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
+ const GrProgramDesc::DescInfo& descInfo,
const GrGLGpu* gpu,
const GrBatchTracker& batchTracker) {
// The descriptor is used as a cache key. Thus when a field of the
@@ -134,7 +135,21 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
// make sure any padding in the header is zeroed.
memset(header, 0, kHeaderSize);
- if (pipeline.readsFragPosition()) {
+ if (descInfo.fReadsDst) {
+ const GrDeviceCoordTexture* dstCopy = pipeline.getDstCopy();
+ SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport());
+ const GrTexture* dstCopyTexture = NULL;
+ if (dstCopy) {
+ dstCopyTexture = dstCopy->texture();
+ }
+ header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
+ gpu->glCaps());
+ SkASSERT(0 != header->fDstReadKey);
+ } else {
+ header->fDstReadKey = 0;
+ }
+
+ if (descInfo.fReadsFragPosition) {
header->fFragPosKey =
GrGLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget(),
gpu->glCaps());
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index f2371556bf..e4db4c3581 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -47,6 +47,8 @@ public:
* general draw information, as well as the specific color, geometry,
* and coverage stages which will be used to generate the GL Program for
* this optstate.
+ * @param DescInfo A descriptor info struct, generated by the optstate, which contains a number
+ * of important facts about the program the built descriptor will represent
* @param GrGLGpu A GL Gpu, the caps and Gpu object are used to output processor specific
* parts of the descriptor.
* @param GrDeviceCoordTexture A dstCopy texture, which may be null if frame buffer fetch is
@@ -56,6 +58,7 @@ public:
static bool Build(GrProgramDesc*,
const GrPrimitiveProcessor&,
const GrPipeline&,
+ const GrProgramDesc::DescInfo&,
const GrGLGpu*,
const GrBatchTracker&);
};
diff --git a/src/gpu/gl/GrGLXferProcessor.cpp b/src/gpu/gl/GrGLXferProcessor.cpp
deleted file mode 100644
index 5e8c00a976..0000000000
--- a/src/gpu/gl/GrGLXferProcessor.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gl/GrGLXferProcessor.h"
-
-#include "GrXferProcessor.h"
-#include "gl/builders/GrGLFragmentShaderBuilder.h"
-#include "gl/builders/GrGLProgramBuilder.h"
-
-void GrGLXferProcessor::emitCode(const EmitArgs& args) {
- if (args.fXP.getDstCopyTexture()) {
- GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
- const char* dstColor = fsBuilder->dstColor();
-
- const char* dstCopyTopLeftName;
- const char* dstCopyCoordScaleName;
-
- fDstCopyTopLeftUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec2f_GrSLType,
- kDefault_GrSLPrecision,
- "DstCopyUpperLeft",
- &dstCopyTopLeftName);
- fDstCopyScaleUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec2f_GrSLType,
- kDefault_GrSLPrecision,
- "DstCopyCoordScale",
- &dstCopyCoordScaleName);
- const char* fragPos = fsBuilder->fragmentPosition();
-
- fsBuilder->codeAppend("// Read color from copy of the destination.\n");
- fsBuilder->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
- fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
- fsBuilder->codeAppendf("vec4 %s = ", dstColor);
- fsBuilder->appendTextureLookup(args.fSamplers[0], "_dstTexCoord", kVec2f_GrSLType);
- fsBuilder->codeAppend(";");
- }
-
- this->onEmitCode(args);
-}
-
-void GrGLXferProcessor::setData(const GrGLProgramDataManager& pdm, const GrXferProcessor& xp) {
- if (xp.getDstCopyTexture()) {
- if (fDstCopyTopLeftUni.isValid()) {
- pdm.set2f(fDstCopyTopLeftUni, static_cast<GrGLfloat>(xp.dstCopyTextureOffset().fX),
- static_cast<GrGLfloat>(xp.dstCopyTextureOffset().fY));
- pdm.set2f(fDstCopyScaleUni, 1.f / xp.getDstCopyTexture()->width(),
- 1.f / xp.getDstCopyTexture()->height());
- } else {
- SkASSERT(!fDstCopyScaleUni.isValid());
- }
- } else {
- SkASSERT(!fDstCopyTopLeftUni.isValid());
- SkASSERT(!fDstCopyScaleUni.isValid());
- }
- this->onSetData(pdm, xp);
-}
-
diff --git a/src/gpu/gl/GrGLXferProcessor.h b/src/gpu/gl/GrGLXferProcessor.h
index 7f60f32fe5..5c92559031 100644
--- a/src/gpu/gl/GrGLXferProcessor.h
+++ b/src/gpu/gl/GrGLXferProcessor.h
@@ -11,7 +11,6 @@
#include "GrGLProcessor.h"
class GrGLXPBuilder;
-class GrXferProcessor;
class GrGLXferProcessor {
public:
@@ -47,25 +46,16 @@ public:
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
*/
- void emitCode(const EmitArgs&);
+ virtual void emitCode(const EmitArgs&) = 0;
/** A GrGLXferProcessor instance can be reused with any GrGLXferProcessor that produces
the same stage key; this function reads data from a GrGLXferProcessor and uploads any
uniform variables required by the shaders created in emitCode(). The GrXferProcessor
parameter is guaranteed to be of the same type that created this GrGLXferProcessor and
- to have an identical processor key as the one that created this GrGLXferProcessor. This
- function calls onSetData on the subclass of GrGLXferProcessor
- */
- void setData(const GrGLProgramDataManager& pdm, const GrXferProcessor& xp);
-
+ to have an identical processor key as the one that created this GrGLXferProcessor. */
+ virtual void setData(const GrGLProgramDataManager&,
+ const GrXferProcessor&) = 0;
private:
- virtual void onEmitCode(const EmitArgs&) = 0;
-
- virtual void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) = 0;
-
- GrGLProgramDataManager::UniformHandle fDstCopyTopLeftUni;
- GrGLProgramDataManager::UniformHandle fDstCopyScaleUni;
-
typedef GrGLProcessor INHERITED;
};
#endif
diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
index 86c622d456..61932f3084 100644
--- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
@@ -179,9 +179,56 @@ const char* GrGLFragmentShaderBuilder::dstColor() {
fbFetchColorName = declared_color_output_name();
}
return fbFetchColorName;
- } else {
+ } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
return kDstCopyColorName;
- }
+ } else {
+ return "";
+ }
+}
+
+void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() {
+ bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey);
+ const char* dstCopyTopLeftName;
+ const char* dstCopyCoordScaleName;
+ const char* dstCopySamplerName;
+ uint32_t configMask;
+ if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstReadKey)) {
+ configMask = kA_GrColorComponentFlag;
+ } else {
+ configMask = kRGBA_GrColorComponentFlags;
+ }
+ fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kSampler2D_GrSLType,
+ kDefault_GrSLPrecision,
+ "DstCopySampler",
+ &dstCopySamplerName);
+ fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec2f_GrSLType,
+ kDefault_GrSLPrecision,
+ "DstCopyUpperLeft",
+ &dstCopyTopLeftName);
+ fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec2f_GrSLType,
+ kDefault_GrSLPrecision,
+ "DstCopyCoordScale",
+ &dstCopyCoordScaleName);
+ const char* fragPos = this->fragmentPosition();
+
+ this->codeAppend("// Read color from copy of the destination.\n");
+ this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
+ fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
+ if (!topDown) {
+ this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
+ }
+ this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName);
+ this->appendTextureLookup(dstCopySamplerName,
+ "_dstTexCoord",
+ configMask,
+ "rgba");
+ this->codeAppend(";");
}
void GrGLFragmentShaderBuilder::enableCustomOutput() {
diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
index 903c5e1d7b..688bbe6269 100644
--- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
+++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
@@ -97,6 +97,7 @@ public:
private:
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
+ void emitCodeToReadDstTexture();
void enableCustomOutput();
void enableSecondaryOutput();
const char* getPrimaryColorOutputName() const;
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index bb278be395..088169622c 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -56,6 +56,12 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp
GrGLProgramBuilder* pb = builder.get();
+ // emit code to read the dst copy texture, if necessary
+ if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != pb->header().fDstReadKey &&
+ !gpu->glCaps().fbFetchSupport()) {
+ pb->fFS.emitCodeToReadDstTexture();
+ }
+
// TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
// seed correctly here
GrGLSLExpr4 inputColor;
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index a9288cc9b0..4b40cefad0 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -267,6 +267,11 @@ public:
// We use the render target height to provide a y-down frag coord when specifying
// origin_upper_left is not supported.
UniformHandle fRTHeightUni;
+
+ // Uniforms for computing texture coords to do the dst-copy lookup
+ UniformHandle fDstCopyTopLeftUni;
+ UniformHandle fDstCopyScaleUni;
+ UniformHandle fDstCopySamplerUni;
};
protected: