From 21b2c53218ab25f4268e3992e51d916076a2a7ee Mon Sep 17 00:00:00 2001 From: bsalomon Date: Thu, 5 Feb 2015 14:18:05 -0800 Subject: [PATCH] Revert of Move DstCopy on gpu into the GrXferProcessor. (patchset #11 id:200001 of https://codereview.chromium.org/885923002/) 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 --- gyp/gpu.gypi | 3 - include/gpu/GrXferProcessor.h | 75 ++++++----------------- include/gpu/effects/GrPorterDuffXferProcessor.h | 25 +++----- src/effects/SkArithmeticMode_gpu.cpp | 31 +++++----- src/effects/SkArithmeticMode_gpu.h | 31 ++++------ src/gpu/GrBatchTarget.cpp | 6 +- src/gpu/GrBatchTarget.h | 3 +- src/gpu/GrDrawTarget.cpp | 54 +++++++++++++--- src/gpu/GrDrawTarget.h | 11 ++-- src/gpu/GrGpu.h | 1 + src/gpu/GrInOrderDrawBuffer.cpp | 34 +++++----- src/gpu/GrInOrderDrawBuffer.h | 13 ++-- src/gpu/GrPipeline.cpp | 17 +++-- src/gpu/GrPipeline.h | 7 ++- src/gpu/GrPipelineBuilder.cpp | 4 +- src/gpu/GrPipelineBuilder.h | 5 +- src/gpu/GrProgramDesc.h | 17 +++++ src/gpu/GrTest.cpp | 1 + src/gpu/GrXferProcessor.cpp | 58 ------------------ src/gpu/effects/GrCoverageSetOpXP.cpp | 28 ++++----- src/gpu/effects/GrCoverageSetOpXP.h | 15 +++-- src/gpu/effects/GrCustomXfermode.cpp | 28 ++++----- src/gpu/effects/GrCustomXfermodePriv.h | 27 ++++---- src/gpu/effects/GrDisableColorXP.cpp | 18 +++--- src/gpu/effects/GrDisableColorXP.h | 15 +++-- src/gpu/effects/GrPorterDuffXferProcessor.cpp | 47 ++++++-------- src/gpu/gl/GrGLGpu.cpp | 4 +- src/gpu/gl/GrGLGpu.h | 1 + src/gpu/gl/GrGLProgram.cpp | 35 +++++++++-- src/gpu/gl/GrGLProgramDesc.cpp | 17 ++++- src/gpu/gl/GrGLProgramDesc.h | 3 + src/gpu/gl/GrGLXferProcessor.cpp | 69 --------------------- src/gpu/gl/GrGLXferProcessor.h | 18 ++---- src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp | 51 ++++++++++++++- src/gpu/gl/builders/GrGLFragmentShaderBuilder.h | 1 + src/gpu/gl/builders/GrGLProgramBuilder.cpp | 6 ++ src/gpu/gl/builders/GrGLProgramBuilder.h | 5 ++ tests/GLProgramsTest.cpp | 4 +- 38 files changed, 374 insertions(+), 414 deletions(-) delete mode 100644 src/gpu/GrXferProcessor.cpp delete mode 100644 src/gpu/gl/GrGLXferProcessor.cpp diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 2036b89..1fbbec8 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -175,7 +175,6 @@ '<(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', @@ -275,8 +274,6 @@ '<(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', diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h index 03d52a9..13e4d26 100644 --- a/include/gpu/GrXferProcessor.h +++ b/include/gpu/GrXferProcessor.h @@ -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() { diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h index e47ec1e..af10fa2 100644 --- a/include/gpu/effects/GrPorterDuffXferProcessor.h +++ b/include/gpu/effects/GrPorterDuffXferProcessor.h @@ -12,22 +12,21 @@ #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(); @@ -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(); return (fSrcCoeff == xpf.fSrcCoeff && fDstCoeff == xpf.fDstCoeff); diff --git a/src/effects/SkArithmeticMode_gpu.cpp b/src/effects/SkArithmeticMode_gpu.cpp index 6379b8d..38bb904 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(); - 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(); 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(); + 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(); + 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 b282e22..2998eab 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(); @@ -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(); if (fK1 != xpf.fK1 || diff --git a/src/gpu/GrBatchTarget.cpp b/src/gpu/GrBatchTarget.cpp index 7a2d14e..494bc47 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/GrBatchTarget.h b/src/gpu/GrBatchTarget.h index 8cd91d3..ff9208f 100644 --- a/src/gpu/GrBatchTarget.h +++ b/src/gpu/GrBatchTarget.h @@ -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); diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index cb60f11..29e33b3 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, ©Rect); 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; diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 1b66517..18265c8 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 8a3c32b..8c458f1 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 3e177ed..e59df80 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 3d1bd7c..bf9237d 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 bd508e9..911169e 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 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 8480c00..24d0b62 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 54d357f..90aee74 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 5743c39..df9a1c8 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 66e0e06..e07e116 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(); } + // 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 T* atOffset() { return reinterpret_cast(reinterpret_cast(fKey.begin()) + OFFSET); diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp index 2f32eb5..05a4a5f 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 e98ae40..0000000 --- a/src/gpu/GrXferProcessor.cpp +++ /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()); -} - diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp index 7025d20..fe286f6 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(); - 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(); 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(); + 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 0bc9e91..a144f97 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(); 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(); return fRegionOp == xpf.fRegionOp; diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp index b77bf2f..9aa7153 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().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().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().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(); + 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 681c805..45a9d30 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(); return fMode == xpf.fMode; diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp index 83b6d23..9383385 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(); } -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(); } -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 da6fa45..d62c320 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 320d943..5038aa3 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(); - 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(); 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(); + 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 6419aa6..dd55abb 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 18f0f74..7eda014 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 eebcf6b..ad63dc4 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(dstCopy->offset().fX), + static_cast(dstCopy->offset().fY)); + fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni, + 1.f / dstCopy->texture()->width(), + 1.f / dstCopy->texture()->height()); + GrGLTexture* texture = static_cast(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 abe2439..32f831e 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 f237155..e4db4c3 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 20ec60d..0000000 --- a/src/gpu/gl/GrGLXferProcessor.cpp +++ /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(xp.dstCopyTextureOffset().fX), - static_cast(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 7f60f32..5c92559 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 86c622d..61932f3 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 903c5e1..688bbe6 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 bb278be..0881696 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 a9288cc..4b40cef 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: diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 30f3458..9b54fa7 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -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 program(GrGLProgramBuilder::CreateProgram(args, gpu)); -- 2.7.4