Revert of Move DstCopy on gpu into the GrXferProcessor. (patchset #11 id:200001 of...
authorbsalomon <bsalomon@google.com>
Thu, 5 Feb 2015 22:18:05 +0000 (14:18 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 5 Feb 2015 22:18:05 +0000 (14:18 -0800)
Reason for revert:
Testing to see if reverting fixes 10.9 bots.

Original issue's description:
> Move DstCopy on gpu into the GrXferProcessor.
>
> BUG=skia:
>
> Committed: https://skia.googlesource.com/skia/+/74a11753604768bf461b80cabb66060e8564d82c
>
> Committed: https://skia.googlesource.com/skia/+/5e1378d0e075a323144ba14e0a4cbcca35eccc69

TBR=joshualitt@google.com,egdaniel@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Review URL: https://codereview.chromium.org/901663007

38 files changed:
gyp/gpu.gypi
include/gpu/GrXferProcessor.h
include/gpu/effects/GrPorterDuffXferProcessor.h
src/effects/SkArithmeticMode_gpu.cpp
src/effects/SkArithmeticMode_gpu.h
src/gpu/GrBatchTarget.cpp
src/gpu/GrBatchTarget.h
src/gpu/GrDrawTarget.cpp
src/gpu/GrDrawTarget.h
src/gpu/GrGpu.h
src/gpu/GrInOrderDrawBuffer.cpp
src/gpu/GrInOrderDrawBuffer.h
src/gpu/GrPipeline.cpp
src/gpu/GrPipeline.h
src/gpu/GrPipelineBuilder.cpp
src/gpu/GrPipelineBuilder.h
src/gpu/GrProgramDesc.h
src/gpu/GrTest.cpp
src/gpu/GrXferProcessor.cpp [deleted file]
src/gpu/effects/GrCoverageSetOpXP.cpp
src/gpu/effects/GrCoverageSetOpXP.h
src/gpu/effects/GrCustomXfermode.cpp
src/gpu/effects/GrCustomXfermodePriv.h
src/gpu/effects/GrDisableColorXP.cpp
src/gpu/effects/GrDisableColorXP.h
src/gpu/effects/GrPorterDuffXferProcessor.cpp
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLGpu.h
src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLProgramDesc.cpp
src/gpu/gl/GrGLProgramDesc.h
src/gpu/gl/GrGLXferProcessor.cpp [deleted file]
src/gpu/gl/GrGLXferProcessor.h
src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
src/gpu/gl/builders/GrGLProgramBuilder.cpp
src/gpu/gl/builders/GrGLProgramBuilder.h
tests/GLProgramsTest.cpp

index 2036b89..1fbbec8 100644 (file)
       '<(skia_src_path)/gpu/GrTextureAccess.cpp',
       '<(skia_src_path)/gpu/GrTRecorder.h',
       '<(skia_src_path)/gpu/GrVertexBuffer.h',
-      '<(skia_src_path)/gpu/GrXferProcessor.cpp',
 
       '<(skia_src_path)/gpu/effects/Gr1DKernelEffect.h',
       '<(skia_src_path)/gpu/effects/GrConfigConversionEffect.cpp',
       '<(skia_src_path)/gpu/gl/GrGLVertexArray.h',
       '<(skia_src_path)/gpu/gl/GrGLVertexBuffer.cpp',
       '<(skia_src_path)/gpu/gl/GrGLVertexBuffer.h',
-      '<(skia_src_path)/gpu/gl/GrGLXferProcessor.cpp',
-      '<(skia_src_path)/gpu/gl/GrGLXferProcessor.h',
 
       # Files for building GLSL shaders
       '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
index 03d52a9..13e4d26 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "GrColor.h"
 #include "GrProcessor.h"
-#include "GrTexture.h"
 #include "GrTypes.h"
 #include "SkXfermode.h"
 
@@ -35,10 +34,11 @@ class GrProcOptInfo;
 class GrXferProcessor : public GrProcessor {
 public:
     /**
-     * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLProcessorKey(...) to get the
-     * specific subclass's key.
-     */ 
-    void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const;
+     * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
+     * processor's GL backend implementation.
+     */
+    virtual void getGLProcessorKey(const GrGLCaps& caps,
+                                   GrProcessorKeyBuilder* b) const = 0;
 
     /** Returns a new instance of the appropriate *GL* implementation class
         for the given GrXferProcessor; caller is responsible for deleting
@@ -103,24 +103,9 @@ public:
 
     virtual void getBlendInfo(BlendInfo* blendInfo) const = 0;
 
+    /** Will this prceossor read the destination pixel value? */
     bool willReadDstColor() const { return fWillReadDstColor; }
 
-    /**
-     * Returns the texture to be used as the destination when reading the dst in the fragment
-     * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
-     * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
-     */
-    const GrTexture* getDstCopyTexture() const { return fDstCopy.getTexture(); }
-
-    /**
-     * Returns the offset into the DstCopyTexture to use when reading it in the shader. This value
-     * is only valid if getDstCopyTexture() != NULL.
-     */
-    const SkIPoint& dstCopyTextureOffset() const {
-        SkASSERT(this->getDstCopyTexture());
-        return fDstCopyTextureOffset;
-    }
-
     /** 
      * Returns whether or not this xferProcossor will set a secondary output to be used with dual
      * source blending.
@@ -138,43 +123,29 @@ public:
         if (this->classID() != that.classID()) {
             return false;
         }
-        if (this->fWillReadDstColor != that.fWillReadDstColor) {
-            return false;
-        }
-        if (this->fDstCopy.getTexture() != that.fDstCopy.getTexture()) {
-            return false;
-        }
-        if (this->fDstCopyTextureOffset != that.fDstCopyTextureOffset) {
-            return false;
-        }
         return this->onIsEqual(that);
     }
    
 protected:
-    GrXferProcessor();
-    GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
+    GrXferProcessor() : fWillReadDstColor(false) {}
 
-private:
     /**
-     * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
-     * processor's GL backend implementation.
+     * If the prceossor subclass will read the destination pixel value then it must call this
+     * function from its constructor. Otherwise, when its generated backend-specific prceossor class
+     * attempts to generate code that reads the destination pixel it will fail.
      */
-    virtual void onGetGLProcessorKey(const GrGLCaps& caps,
-                                     GrProcessorKeyBuilder* b) const = 0;
+    void setWillReadDstColor() { fWillReadDstColor = true; }
 
+private:
     virtual bool onIsEqual(const GrXferProcessor&) const = 0;
 
-    bool                    fWillReadDstColor;
-    SkIPoint                fDstCopyTextureOffset;
-    GrTextureAccess         fDstCopy;
+    bool         fWillReadDstColor;
 
     typedef GrFragmentProcessor INHERITED;
 };
 
 GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
 
-///////////////////////////////////////////////////////////////////////////////
-
 /**
  * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
  * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
@@ -188,10 +159,8 @@ GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
  */
 class GrXPFactory : public SkRefCnt {
 public:
-    GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
-                                         const GrProcOptInfo& coveragePOI,
-                                         const GrDeviceCoordTexture* dstCopy,
-                                         const GrDrawTargetCaps& caps) const;
+    virtual GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+                                                 const GrProcOptInfo& coveragePOI) const = 0;
 
     /**
      * This function returns true if the GrXferProcessor generated from this factory will be able to
@@ -233,7 +202,10 @@ public:
      */
     virtual bool canTweakAlphaForCoverage() const = 0;
 
-    bool willNeedDstCopy(const GrDrawTargetCaps& caps) const; 
+    /**
+     *  Returns true if the XP generated by this factory will read dst.
+     */
+    virtual bool willReadDst() const = 0;
 
     bool isEqual(const GrXPFactory& that) const {
         if (this->classID() != that.classID()) {
@@ -260,15 +232,6 @@ protected:
     uint32_t fClassID;
 
 private:
-    virtual GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
-                                                   const GrProcOptInfo& coveragePOI,
-                                                   const GrDeviceCoordTexture* dstCopy) const = 0;
-    /**
-     *  Returns true if the XP generated by this factory will explicitly read dst in the fragment
-     *  shader.
-     */
-    virtual bool willReadDstColor() const = 0;
-
     virtual bool onIsEqual(const GrXPFactory&) const = 0;
 
     static uint32_t GenClassID() {
index e47ec1e..af10fa2 100644 (file)
 #include "GrXferProcessor.h"
 #include "SkXfermode.h"
 
-class GrDrawTargetCaps;
 class GrProcOptInfo;
 
 class GrPorterDuffXferProcessor : public GrXferProcessor {
 public:
     static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend,
-                                   GrColor constant, const GrDeviceCoordTexture* dstCopy,
-                                   bool willReadDstColor) {
-        return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend, constant, dstCopy,
-                                                      willReadDstColor));
+                                   GrColor constant = 0) {
+        return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend, constant));
     }
 
     ~GrPorterDuffXferProcessor() SK_OVERRIDE;
 
     const char* name() const SK_OVERRIDE { return "Porter Duff"; }
 
+    void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
     GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
 
     bool hasSecondaryOutput() const SK_OVERRIDE;
@@ -76,10 +75,7 @@ public:
     }
 
 private:
-    GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant,
-                              const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
-
-    void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+    GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant);
 
     bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
         const GrPorterDuffXferProcessor& xp = xpBase.cast<GrPorterDuffXferProcessor>();
@@ -123,6 +119,9 @@ public:
         return SkNEW_ARGS(GrPorterDuffXPFactory, (src, dst));
     }
 
+    GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+                                         const GrProcOptInfo& coveragePOI) const SK_OVERRIDE;
+
     bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE;
 
     bool canApplyCoverage(const GrProcOptInfo& colorPOI,
@@ -133,15 +132,11 @@ public:
     void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
                             GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
 
+    bool willReadDst() const SK_OVERRIDE { return false; }
+
 private:
     GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst); 
 
-    GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
-                                           const GrProcOptInfo& coveragePOI,
-                                           const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
-
-    bool willReadDstColor() const SK_OVERRIDE;
-
     bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
         const GrPorterDuffXPFactory& xpf = xpfBase.cast<GrPorterDuffXPFactory>();
         return (fSrcCoeff == xpf.fSrcCoeff && fDstCoeff == xpf.fDstCoeff);
index 6379b8d..38bb904 100644 (file)
@@ -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<GrArithmeticXP>();
+    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);
 }
 
index b282e22..2998eab 100644 (file)
@@ -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 ||
index 7a2d14e..494bc47 100644 (file)
@@ -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++) {
index 8cd91d3..ff9208f 100644 (file)
@@ -56,7 +56,8 @@ public:
             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);
 
index cb60f11..29e33b3 100644 (file)
@@ -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) {
@@ -470,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);
     }
 }
 
@@ -509,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);
     }
 }
 
@@ -530,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() {
@@ -620,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,
@@ -655,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,
@@ -766,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;
@@ -779,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;
index 1b66517..18265c8 100644 (file)
@@ -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;
index 8a3c32b..8c458f1 100644 (file)
@@ -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
index 3e177ed..e59df80 100644 (file)
@@ -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;
index 3d1bd7c..bf9237d 100644 (file)
@@ -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();
index bd508e9..911169e 100644 (file)
@@ -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;
     }
 
index 8480c00..24d0b62 100644 (file)
@@ -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.
index 54d357f..90aee74 100644 (file)
@@ -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) {
index 5743c39..df9a1c8 100644 (file)
@@ -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.
index 66e0e06..e07e116 100644 (file)
@@ -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);
index 2f32eb5..05a4a5f 100644 (file)
@@ -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 (file)
index e98ae40..0000000
+++ /dev/null
@@ -1,58 +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();
-        this->addTextureAccess(&fDstCopy);
-    }
-}
-
-void GrXferProcessor::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
-    uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
-    if (this->getDstCopyTexture() &&
-        kTopLeft_GrSurfaceOrigin == this->getDstCopyTexture()->origin()) {
-        key |= 0x2;
-    }
-    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());
-}
-
index 7025d20..fe286f6 100644 (file)
@@ -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);
 }
 
index 0bc9e91..a144f97 100644 (file)
@@ -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;
index b77bf2f..9aa7153 100644 (file)
@@ -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);
 }
 
index 681c805..45a9d30 100644 (file)
@@ -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;
index 83b6d23..9383385 100644 (file)
@@ -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();
 }
 
index da6fa45..d62c320 100644 (file)
@@ -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;
     }
index 320d943..5038aa3 100644 (file)
@@ -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,
index 6419aa6..dd55abb 100644 (file)
@@ -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");
     }
 }
index 18f0f74..7eda014 100644 (file)
@@ -108,6 +108,7 @@ public:
     void buildProgramDesc(GrProgramDesc*,
                           const GrPrimitiveProcessor&,
                           const GrPipeline&,
+                          const GrProgramDesc::DescInfo&,
                           const GrBatchTracker&) const SK_OVERRIDE;
 
 private:
index eebcf6b..ad63dc4 100644 (file)
@@ -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
index abe2439..32f831e 100644 (file)
@@ -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());
index f237155..e4db4c3 100644 (file)
@@ -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 (file)
index 20ec60d..0000000
+++ /dev/null
@@ -1,69 +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()) {
-
-        bool topDown = kTopLeft_GrSurfaceOrigin == args.fXP.getDstCopyTexture()->origin();
-
-        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);
-
-        if (!topDown) {
-            fsBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
-        }
-
-        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);
-}
-
index 7f60f32..5c92559 100644 (file)
@@ -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
index 86c622d..61932f3 100644 (file)
@@ -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() {
index 903c5e1..688bbe6 100644 (file)
@@ -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;
index bb278be..0881696 100644 (file)
@@ -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;
index a9288cc..4b40cef 100644 (file)
@@ -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:
index 30f3458..9b54fa7 100644 (file)
@@ -298,7 +298,7 @@ bool GrDrawTarget::programUnitTest(int maxStages) {
         } else {
             primProc = pathProc.get();
         }
-        if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, NULL)) {
+        if (!this->setupDstReadIfNecessary(&pipelineBuilder, &dstCopy, NULL)) {
             SkDebugf("Couldn't setup dst read texture");
             return false;
         }
@@ -313,7 +313,7 @@ bool GrDrawTarget::programUnitTest(int maxStages) {
         primProc->initBatchTracker(&bt, pipeline.getInitBatchTracker());
 
         GrProgramDesc desc;
-        gpu->buildProgramDesc(&desc, *primProc, pipeline, bt);
+        gpu->buildProgramDesc(&desc, *primProc, pipeline, pipeline.descInfo(), bt);
 
         GrGpu::DrawArgs args(primProc, &pipeline, &desc, &bt);
         SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(args, gpu));