'<(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',
#include "GrColor.h"
#include "GrProcessor.h"
-#include "GrTexture.h"
#include "GrTypes.h"
#include "SkXfermode.h"
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
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.
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
*/
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
*/
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()) {
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() {
#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;
}
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>();
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,
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);
~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();
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;
///////////////////////////////////////////////////////////////////////////////
-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);
}
#if SK_SUPPORT_GPU
#include "GrCoordTransform.h"
-#include "GrDrawTargetCaps.h"
#include "GrFragmentProcessor.h"
#include "GrTextureAccess.h"
#include "GrTypes.h"
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; }
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>();
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;
}
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 ||
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++) {
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++) {
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);
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) {
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);
}
}
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);
}
}
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() {
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,
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,
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;
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;
// 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);
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,
const GrPath*,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) = 0;
+ const GrDeviceCoordTexture* dstCopy) = 0;
virtual void onDrawPaths(const GrPipelineBuilder&,
const GrPathProcessor*,
const GrPathRange*,
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;
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
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;
}
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;
}
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));
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;
}
if (ss->fPrimitiveProcessor) {
this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
ss->fPipeline,
+ ss->fPipeline.descInfo(),
ss->fBatchTracker);
}
currentState = ss;
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;
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;
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,
const GrPath*,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) SK_OVERRIDE;
+ const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
void onDrawPaths(const GrPipelineBuilder&,
const GrPathProcessor*,
const GrPathRange*,
int count,
const GrScissorState&,
const GrStencilSettings&,
- const SkRect* devBounds) SK_OVERRIDE;
+ const GrDeviceCoordTexture*) SK_OVERRIDE;
void onClear(const SkIRect* rect,
GrColor color,
bool canIgnoreRect,
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();
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) {
fScissorState = scissorState;
fStencilSettings = pipelineBuilder.getStencil();
fDrawFace = pipelineBuilder.getDrawFace();
+ // TODO move this out of GrPipeline
+ if (dstCopy) {
+ fDstCopy = *dstCopy;
+ }
fFlags = 0;
if (pipelineBuilder.isHWAntialias()) {
this->adjustProgramFromOptimizations(pipelineBuilder, optFlags, colorPOI, coveragePOI,
&firstColorStageIdx, &firstCoverageStageIdx);
+ fDescInfo.fReadsDst = fXferProcessor->willReadDstColor();
+
bool usesLocalCoords = false;
// Copy Stages from PipelineBuilder to Pipeline
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;
}
}
}
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;
}
///////////////////////////////////////////////////////////////////////////
- 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; }
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.
//////////////////////////////////////////////////////////////////////////////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) {
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.
}
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.
// 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);
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 {}
+++ /dev/null
-/*
- * 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());
-}
-
~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();
}
}
- 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;
};
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);
}
}
}
-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);
}
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; }
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 &&
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;
}
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;
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();
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);
}
#define GrCustomXfermodePriv_DEFINED
#include "GrCoordTransform.h"
-#include "GrDrawTargetCaps.h"
#include "GrFragmentProcessor.h"
#include "GrTextureAccess.h"
#include "GrXferProcessor.h"
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));
}
}
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; }
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;
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;
}
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;
~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.
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;
};
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);
}
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();
}
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; }
private:
GrDisableColorXP();
- void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
-
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
return true;
}
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;
}
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;
}
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()) {
}
}
- 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)
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);
}
}
}
-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;
}
output->fWillBlendWithDst = false;
}
-bool GrPorterDuffXPFactory::willReadDstColor() const {
- return false;
-}
-
GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
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");
}
}
void buildProgramDesc(GrProgramDesc*,
const GrPrimitiveProcessor&,
const GrPipeline&,
+ const GrProgramDesc::DescInfo&,
const GrBatchTracker&) const SK_OVERRIDE;
private:
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);
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
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
// 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());
* 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
static bool Build(GrProgramDesc*,
const GrPrimitiveProcessor&,
const GrPipeline&,
+ const GrProgramDesc::DescInfo&,
const GrGLGpu*,
const GrBatchTracker&);
};
+++ /dev/null
-/*
- * 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);
-}
-
#include "GrGLProcessor.h"
class GrGLXPBuilder;
-class GrXferProcessor;
class GrGLXferProcessor {
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
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() {
private:
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
+ void emitCodeToReadDstTexture();
void enableCustomOutput();
void enableSecondaryOutput();
const char* getPrimaryColorOutputName() const;
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;
// 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:
} 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;
}
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));