Move DstCopy on gpu into the GrXferProcessor.
BUG=skia: Committed: https://skia.googlesource.com/skia/+/74a11753604768bf461b80cabb66060e8564d82c Review URL: https://codereview.chromium.org/885923002
This commit is contained in:
parent
2fdd29d6e5
commit
5e1378d0e0
@ -175,6 +175,7 @@
|
||||
'<(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',
|
||||
@ -274,6 +275,8 @@
|
||||
'<(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',
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "GrColor.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrTypes.h"
|
||||
#include "SkXfermode.h"
|
||||
|
||||
@ -34,11 +35,10 @@ class GrProcOptInfo;
|
||||
class GrXferProcessor : public GrProcessor {
|
||||
public:
|
||||
/**
|
||||
* 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;
|
||||
* Sets a unique key on the GrProcessorKeyBuilder calls onGetGLProcessorKey(...) to get the
|
||||
* specific subclass's key.
|
||||
*/
|
||||
void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const;
|
||||
|
||||
/** Returns a new instance of the appropriate *GL* implementation class
|
||||
for the given GrXferProcessor; caller is responsible for deleting
|
||||
@ -103,9 +103,24 @@ 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.
|
||||
@ -123,29 +138,43 @@ 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() : fWillReadDstColor(false) {}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void setWillReadDstColor() { fWillReadDstColor = true; }
|
||||
GrXferProcessor();
|
||||
GrXferProcessor(const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
|
||||
* processor's GL backend implementation.
|
||||
*/
|
||||
virtual void onGetGLProcessorKey(const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const = 0;
|
||||
|
||||
virtual bool onIsEqual(const GrXferProcessor&) const = 0;
|
||||
|
||||
bool fWillReadDstColor;
|
||||
bool fWillReadDstColor;
|
||||
SkIPoint fDstCopyTextureOffset;
|
||||
GrTextureAccess fDstCopy;
|
||||
|
||||
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
|
||||
@ -159,8 +188,10 @@ GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);
|
||||
*/
|
||||
class GrXPFactory : public SkRefCnt {
|
||||
public:
|
||||
virtual GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI) const = 0;
|
||||
GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
const GrDeviceCoordTexture* dstCopy,
|
||||
const GrDrawTargetCaps& caps) const;
|
||||
|
||||
/**
|
||||
* This function returns true if the GrXferProcessor generated from this factory will be able to
|
||||
@ -202,10 +233,7 @@ public:
|
||||
*/
|
||||
virtual bool canTweakAlphaForCoverage() const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the XP generated by this factory will read dst.
|
||||
*/
|
||||
virtual bool willReadDst() const = 0;
|
||||
bool willNeedDstCopy(const GrDrawTargetCaps& caps) const;
|
||||
|
||||
bool isEqual(const GrXPFactory& that) const {
|
||||
if (this->classID() != that.classID()) {
|
||||
@ -232,6 +260,15 @@ 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() {
|
||||
|
@ -12,21 +12,22 @@
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkXfermode.h"
|
||||
|
||||
class GrDrawTargetCaps;
|
||||
class GrProcOptInfo;
|
||||
|
||||
class GrPorterDuffXferProcessor : public GrXferProcessor {
|
||||
public:
|
||||
static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend,
|
||||
GrColor constant = 0) {
|
||||
return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend, constant));
|
||||
GrColor constant, const GrDeviceCoordTexture* dstCopy,
|
||||
bool willReadDstColor) {
|
||||
return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend, constant, dstCopy,
|
||||
willReadDstColor));
|
||||
}
|
||||
|
||||
~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;
|
||||
@ -75,7 +76,10 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant);
|
||||
GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant,
|
||||
const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
|
||||
|
||||
void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
|
||||
const GrPorterDuffXferProcessor& xp = xpBase.cast<GrPorterDuffXferProcessor>();
|
||||
@ -119,9 +123,6 @@ 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,
|
||||
@ -132,11 +133,15 @@ public:
|
||||
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
|
||||
|
||||
bool willReadDst() const SK_OVERRIDE { return false; }
|
||||
|
||||
private:
|
||||
GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst);
|
||||
|
||||
GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
|
||||
|
||||
bool willReadDstColor() const SK_OVERRIDE;
|
||||
|
||||
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
|
||||
const GrPorterDuffXPFactory& xpf = xpfBase.cast<GrPorterDuffXPFactory>();
|
||||
return (fSrcCoeff == xpf.fSrcCoeff && fDstCoeff == xpf.fDstCoeff);
|
||||
|
@ -166,7 +166,15 @@ public:
|
||||
|
||||
~GLArithmeticXP() SK_OVERRIDE {}
|
||||
|
||||
void emitCode(const EmitArgs& args) 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 {
|
||||
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
||||
|
||||
const char* dstColor = fsBuilder->dstColor();
|
||||
@ -184,21 +192,13 @@ public:
|
||||
args.fInputCoverage, dstColor);
|
||||
}
|
||||
|
||||
void setData(const GrGLProgramDataManager& pdman,
|
||||
const GrXferProcessor& processor) SK_OVERRIDE {
|
||||
void onSetData(const GrGLProgramDataManager& pdman,
|
||||
const GrXferProcessor& processor) SK_OVERRIDE {
|
||||
const GrArithmeticXP& arith = processor.cast<GrArithmeticXP>();
|
||||
pdman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
|
||||
fEnforcePMColor = arith.enforcePMColor();
|
||||
};
|
||||
|
||||
static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const GrArithmeticXP& arith = processor.cast<GrArithmeticXP>();
|
||||
uint32_t key = arith.enforcePMColor() ? 1 : 0;
|
||||
b->add32(key);
|
||||
}
|
||||
|
||||
private:
|
||||
GrGLProgramDataManager::UniformHandle fKUni;
|
||||
bool fEnforcePMColor;
|
||||
|
||||
@ -207,17 +207,18 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrArithmeticXP::GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor)
|
||||
: fK1(k1)
|
||||
GrArithmeticXP::GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor,
|
||||
const GrDeviceCoordTexture* dstCopy, bool willReadDstColor)
|
||||
: INHERITED(dstCopy, willReadDstColor)
|
||||
, fK1(k1)
|
||||
, fK2(k2)
|
||||
, fK3(k3)
|
||||
, fK4(k4)
|
||||
, fEnforcePMColor(enforcePMColor) {
|
||||
this->initClassID<GrArithmeticXP>();
|
||||
this->setWillReadDstColor();
|
||||
}
|
||||
|
||||
void GrArithmeticXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
void GrArithmeticXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
GLArithmeticXP::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrDrawTargetCaps.h"
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "GrTextureAccess.h"
|
||||
#include "GrTypes.h"
|
||||
@ -72,16 +73,17 @@ private:
|
||||
|
||||
class GrArithmeticXP : public GrXferProcessor {
|
||||
public:
|
||||
static GrXferProcessor* Create(float k1, float k2, float k3, float k4, bool enforcePMColor) {
|
||||
return SkNEW_ARGS(GrArithmeticXP, (k1, k2, k3, k4, enforcePMColor));
|
||||
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));
|
||||
}
|
||||
|
||||
~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; }
|
||||
@ -105,7 +107,10 @@ public:
|
||||
bool enforcePMColor() const { return fEnforcePMColor; }
|
||||
|
||||
private:
|
||||
GrArithmeticXP(float k1, float k2, float k3, float k4, bool enforcePMColor);
|
||||
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;
|
||||
|
||||
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
|
||||
const GrArithmeticXP& xp = xpBase.cast<GrArithmeticXP>();
|
||||
@ -133,11 +138,6 @@ 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,11 +154,18 @@ public:
|
||||
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
|
||||
|
||||
bool willReadDst() const SK_OVERRIDE { return true; }
|
||||
|
||||
private:
|
||||
GrArithmeticXPFactory(float k1, float k2, float k3, float k4, bool enforcePMColor);
|
||||
|
||||
GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE {
|
||||
return GrArithmeticXP::Create(fK1, fK2, fK3, fK4, fEnforcePMColor, dstCopy,
|
||||
this->willReadDstColor());
|
||||
}
|
||||
|
||||
bool willReadDstColor() const SK_OVERRIDE { return true; }
|
||||
|
||||
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
|
||||
const GrArithmeticXPFactory& xpf = xpfBase.cast<GrArithmeticXPFactory>();
|
||||
if (fK1 != xpf.fK1 ||
|
||||
|
@ -21,8 +21,7 @@ void GrBatchTarget::flush() {
|
||||
BufferedFlush* bf = iter.get();
|
||||
const GrPipeline* pipeline = bf->fPipeline;
|
||||
const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get();
|
||||
fGpu->buildProgramDesc(&desc, *primProc, *pipeline, pipeline->descInfo(),
|
||||
bf->fBatchTracker);
|
||||
fGpu->buildProgramDesc(&desc, *primProc, *pipeline, bf->fBatchTracker);
|
||||
|
||||
GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker);
|
||||
for (int i = 0; i < bf->fDraws.count(); i++) {
|
||||
@ -40,8 +39,7 @@ 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, pipeline->descInfo(),
|
||||
bf->fBatchTracker);
|
||||
fGpu->buildProgramDesc(&desc, *primProc, *pipeline, bf->fBatchTracker);
|
||||
|
||||
GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker);
|
||||
for (int i = 0; i < bf->fDraws.count(); i++) {
|
||||
|
@ -56,8 +56,7 @@ public:
|
||||
BufferedFlush* bf = fIter.get();
|
||||
const GrPipeline* pipeline = bf->fPipeline;
|
||||
const GrPrimitiveProcessor* primProc = bf->fPrimitiveProcessor.get();
|
||||
fGpu->buildProgramDesc(&desc, *primProc, *pipeline, pipeline->descInfo(),
|
||||
bf->fBatchTracker);
|
||||
fGpu->buildProgramDesc(&desc, *primProc, *pipeline, bf->fBatchTracker);
|
||||
|
||||
GrGpu::DrawArgs args(primProc, pipeline, &desc, &bf->fBatchTracker);
|
||||
|
||||
|
@ -384,15 +384,15 @@ bool GrDrawTarget::checkDraw(const GrPipelineBuilder& pipelineBuilder,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrDrawTarget::setupDstReadIfNecessary(GrPipelineBuilder* pipelineBuilder,
|
||||
bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
|
||||
GrDeviceCoordTexture* dstCopy,
|
||||
const SkRect* drawBounds) {
|
||||
if (this->caps()->dstReadInShaderSupport() || !pipelineBuilder->willEffectReadDstColor()) {
|
||||
if (!pipelineBuilder.willXPNeedDstCopy(*this->caps())) {
|
||||
return true;
|
||||
}
|
||||
SkIRect copyRect;
|
||||
const GrClipData* clip = this->getClip();
|
||||
GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
|
||||
GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
|
||||
clip->getConservativeBounds(rt, ©Rect);
|
||||
|
||||
if (drawBounds) {
|
||||
@ -470,14 +470,9 @@ 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, dstCopy.texture() ? &dstCopy : NULL);
|
||||
this->onDraw(*pipelineBuilder, gp, info, scissorState);
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,15 +509,9 @@ 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, dstCopy.texture() ? &dstCopy : NULL);
|
||||
this->onDraw(*pipelineBuilder, gp, info, scissorState);
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,12 +530,7 @@ void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder,
|
||||
return;
|
||||
}
|
||||
|
||||
GrDeviceCoordTexture dstCopy;
|
||||
if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->onDrawBatch(batch, *pipelineBuilder, scissorState, dstCopy.texture() ? &dstCopy : NULL);
|
||||
this->onDrawBatch(batch, *pipelineBuilder, scissorState, devBounds);
|
||||
}
|
||||
|
||||
static const GrStencilSettings& winding_path_stencil_settings() {
|
||||
@ -636,13 +620,8 @@ 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,
|
||||
dstCopy.texture() ? &dstCopy : NULL);
|
||||
&devBounds);
|
||||
}
|
||||
|
||||
void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
|
||||
@ -676,18 +655,12 @@ void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
|
||||
pipelineBuilder->getRenderTarget()->getStencilBuffer(),
|
||||
&stencilSettings);
|
||||
|
||||
// Don't compute a bounding box for setupDstReadIfNecessary(), we'll opt
|
||||
// Don't compute a bounding box for dst copy texture, 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,
|
||||
dstCopy.texture() ? &dstCopy : NULL);
|
||||
transformType, count, scissorState, stencilSettings, NULL);
|
||||
}
|
||||
|
||||
void GrDrawTarget::clear(const SkIRect* rect,
|
||||
@ -793,12 +766,6 @@ 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;
|
||||
@ -812,8 +779,7 @@ void GrDrawTarget::drawIndexedInstances(GrPipelineBuilder* pipelineBuilder,
|
||||
info.fVertexCount,
|
||||
info.fIndexCount)) {
|
||||
this->setDrawBuffers(&info, gp->getVertexStride());
|
||||
this->onDraw(*pipelineBuilder, gp, info, scissorState,
|
||||
dstCopy.texture() ? &dstCopy : NULL);
|
||||
this->onDraw(*pipelineBuilder, gp, info, scissorState);
|
||||
}
|
||||
info.fStartVertex += info.fVertexCount;
|
||||
instanceCount -= info.fInstanceCount;
|
||||
|
@ -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(GrPipelineBuilder*,
|
||||
bool setupDstReadIfNecessary(const GrPipelineBuilder&,
|
||||
GrDeviceCoordTexture* dstCopy,
|
||||
const SkRect* drawBounds);
|
||||
|
||||
@ -720,12 +720,11 @@ private:
|
||||
virtual void onDraw(const GrPipelineBuilder&,
|
||||
const GrGeometryProcessor*,
|
||||
const DrawInfo&,
|
||||
const GrScissorState&,
|
||||
const GrDeviceCoordTexture* dstCopy) = 0;
|
||||
const GrScissorState&) = 0;
|
||||
virtual void onDrawBatch(GrBatch*,
|
||||
const GrPipelineBuilder&,
|
||||
const GrScissorState&,
|
||||
const GrDeviceCoordTexture* dstCopy) = 0;
|
||||
const SkRect* devBounds) = 0;
|
||||
// TODO copy in order drawbuffer onDrawRect to here
|
||||
virtual void onDrawRect(GrPipelineBuilder*,
|
||||
GrColor color,
|
||||
@ -744,7 +743,7 @@ private:
|
||||
const GrPath*,
|
||||
const GrScissorState&,
|
||||
const GrStencilSettings&,
|
||||
const GrDeviceCoordTexture* dstCopy) = 0;
|
||||
const SkRect* devBounds) = 0;
|
||||
virtual void onDrawPaths(const GrPipelineBuilder&,
|
||||
const GrPathProcessor*,
|
||||
const GrPathRange*,
|
||||
@ -755,7 +754,7 @@ private:
|
||||
int count,
|
||||
const GrScissorState&,
|
||||
const GrStencilSettings&,
|
||||
const GrDeviceCoordTexture*) = 0;
|
||||
const SkRect* devBounds) = 0;
|
||||
|
||||
virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
|
||||
GrRenderTarget* renderTarget) = 0;
|
||||
|
@ -298,7 +298,6 @@ 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
|
||||
|
@ -247,14 +247,13 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBu
|
||||
void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrGeometryProcessor* gp,
|
||||
const DrawInfo& info,
|
||||
const GrScissorState& scissorState,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
const GrScissorState& scissorState) {
|
||||
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, dstCopy)) {
|
||||
if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, info.getDevBounds())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -276,8 +275,8 @@ void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
|
||||
void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
|
||||
const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrScissorState& scissorState,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, dstCopy)) {
|
||||
const SkRect* devBounds) {
|
||||
if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, devBounds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -316,11 +315,11 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrPath* path,
|
||||
const GrScissorState& scissorState,
|
||||
const GrStencilSettings& stencilSettings,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
const SkRect* devBounds) {
|
||||
this->closeBatch();
|
||||
|
||||
// TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
|
||||
if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
|
||||
if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
|
||||
return;
|
||||
}
|
||||
DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
|
||||
@ -338,14 +337,14 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
|
||||
int count,
|
||||
const GrScissorState& scissorState,
|
||||
const GrStencilSettings& stencilSettings,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
const SkRect* devBounds) {
|
||||
SkASSERT(pathRange);
|
||||
SkASSERT(indices);
|
||||
SkASSERT(transformValues);
|
||||
|
||||
this->closeBatch();
|
||||
|
||||
if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, dstCopy)) {
|
||||
if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -489,7 +488,6 @@ void GrInOrderDrawBuffer::onFlush() {
|
||||
if (ss->fPrimitiveProcessor) {
|
||||
this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
|
||||
ss->fPipeline,
|
||||
ss->fPipeline.descInfo(),
|
||||
ss->fBatchTracker);
|
||||
}
|
||||
currentState = ss;
|
||||
@ -584,10 +582,14 @@ bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
|
||||
bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrPrimitiveProcessor* primProc,
|
||||
const GrScissorState& scissor,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
const SkRect* devBounds) {
|
||||
GrDeviceCoordTexture dstCopy;
|
||||
if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
@ -612,13 +614,17 @@ bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipe
|
||||
bool GrInOrderDrawBuffer::recordStateAndShouldDraw(GrBatch* batch,
|
||||
const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrScissorState& scissor,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
const SkRect* devBounds) {
|
||||
GrDeviceCoordTexture dstCopy;
|
||||
if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
|
||||
return false;
|
||||
}
|
||||
// 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;
|
||||
|
@ -233,12 +233,11 @@ private:
|
||||
void onDraw(const GrPipelineBuilder&,
|
||||
const GrGeometryProcessor*,
|
||||
const DrawInfo&,
|
||||
const GrScissorState&,
|
||||
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
|
||||
const GrScissorState&) SK_OVERRIDE;
|
||||
void onDrawBatch(GrBatch*,
|
||||
const GrPipelineBuilder&,
|
||||
const GrScissorState&,
|
||||
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
|
||||
const SkRect* devBounds) SK_OVERRIDE;
|
||||
void onDrawRect(GrPipelineBuilder*,
|
||||
GrColor,
|
||||
const SkMatrix& viewMatrix,
|
||||
@ -256,7 +255,7 @@ private:
|
||||
const GrPath*,
|
||||
const GrScissorState&,
|
||||
const GrStencilSettings&,
|
||||
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
|
||||
const SkRect* devBounds) SK_OVERRIDE;
|
||||
void onDrawPaths(const GrPipelineBuilder&,
|
||||
const GrPathProcessor*,
|
||||
const GrPathRange*,
|
||||
@ -267,7 +266,7 @@ private:
|
||||
int count,
|
||||
const GrScissorState&,
|
||||
const GrStencilSettings&,
|
||||
const GrDeviceCoordTexture*) SK_OVERRIDE;
|
||||
const SkRect* devBounds) SK_OVERRIDE;
|
||||
void onClear(const SkIRect* rect,
|
||||
GrColor color,
|
||||
bool canIgnoreRect,
|
||||
@ -288,11 +287,11 @@ private:
|
||||
bool SK_WARN_UNUSED_RESULT recordStateAndShouldDraw(const GrPipelineBuilder&,
|
||||
const GrPrimitiveProcessor*,
|
||||
const GrScissorState&,
|
||||
const GrDeviceCoordTexture*);
|
||||
const SkRect*);
|
||||
bool SK_WARN_UNUSED_RESULT recordStateAndShouldDraw(GrBatch*,
|
||||
const GrPipelineBuilder&,
|
||||
const GrScissorState&,
|
||||
const GrDeviceCoordTexture*);
|
||||
const SkRect*);
|
||||
|
||||
// We lazily record clip changes in order to skip clips that have no effect.
|
||||
void recordClipIfNecessary();
|
||||
|
@ -48,7 +48,7 @@ void GrPipeline::internalConstructor(const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrDeviceCoordTexture* dstCopy) {
|
||||
// Create XferProcessor from DS's XPFactory
|
||||
SkAutoTUnref<GrXferProcessor> xferProcessor(
|
||||
pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
|
||||
pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI, dstCopy, caps));
|
||||
|
||||
GrColor overrideColor = GrColor_ILLEGAL;
|
||||
if (colorPOI.firstEffectiveStageIndex() != 0) {
|
||||
@ -82,10 +82,6 @@ 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()) {
|
||||
@ -107,8 +103,6 @@ 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
|
||||
@ -142,20 +136,20 @@ void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelin
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
int* firstColorStageIdx,
|
||||
int* firstCoverageStageIdx) {
|
||||
fDescInfo.fReadsFragPosition = false;
|
||||
fReadsFragPosition = false;
|
||||
|
||||
if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
|
||||
(flags & GrXferProcessor::kOverrideColor_OptFlag)) {
|
||||
*firstColorStageIdx = pipelineBuilder.numColorStages();
|
||||
} else {
|
||||
fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
|
||||
fReadsFragPosition = colorPOI.readsFragPosition();
|
||||
}
|
||||
|
||||
if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
|
||||
*firstCoverageStageIdx = pipelineBuilder.numCoverageStages();
|
||||
} else {
|
||||
if (coveragePOI.readsFragPosition()) {
|
||||
fDescInfo.fReadsFragPosition = true;
|
||||
fReadsFragPosition = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,8 +163,7 @@ bool GrPipeline::isEqual(const GrPipeline& that) const {
|
||||
this->fScissorState != that.fScissorState ||
|
||||
this->fFlags != that.fFlags ||
|
||||
this->fStencilSettings != that.fStencilSettings ||
|
||||
this->fDrawFace != that.fDrawFace ||
|
||||
this->fDstCopy.texture() != that.fDstCopy.texture()) {
|
||||
this->fDrawFace != that.fDrawFace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -132,9 +132,7 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const GrDeviceCoordTexture* getDstCopy() const { return fDstCopy.texture() ? &fDstCopy : NULL; }
|
||||
|
||||
const GrProgramDesc::DescInfo& descInfo() const { return fDescInfo; }
|
||||
bool readsFragPosition() const { return fReadsFragPosition; }
|
||||
|
||||
const GrPipelineInfo& getInitBatchTracker() const { return fInitBT; }
|
||||
|
||||
@ -177,11 +175,10 @@ private:
|
||||
GrScissorState fScissorState;
|
||||
GrStencilSettings fStencilSettings;
|
||||
GrPipelineBuilder::DrawFace fDrawFace;
|
||||
GrDeviceCoordTexture fDstCopy;
|
||||
uint32_t fFlags;
|
||||
ProgramXferProcessor fXferProcessor;
|
||||
FragmentStageArray fFragmentStages;
|
||||
GrProgramDesc::DescInfo fDescInfo;
|
||||
bool fReadsFragPosition;
|
||||
GrPipelineInfo fInitBT;
|
||||
|
||||
// This function is equivalent to the offset into fFragmentStages where coverage stages begin.
|
||||
|
@ -101,8 +101,8 @@ bool GrPipelineBuilder::canUseFracCoveragePrimProc(GrColor color,
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////s
|
||||
|
||||
bool GrPipelineBuilder::willEffectReadDstColor() const {
|
||||
return this->getXPFactory()->willReadDst();
|
||||
bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps) const {
|
||||
return this->getXPFactory()->willNeedDstCopy(caps);
|
||||
}
|
||||
|
||||
void GrPipelineBuilder::AutoRestoreEffects::set(GrPipelineBuilder* pipelineBuilder) {
|
||||
|
@ -102,10 +102,9 @@ public:
|
||||
const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
|
||||
|
||||
/**
|
||||
* Checks whether the xp will read the dst pixel color.
|
||||
* TODO: remove when we have dstCpy contained inside of GrXP
|
||||
* Checks whether the xp will need a copy of the destination to correctly blend.
|
||||
*/
|
||||
bool willEffectReadDstColor() const;
|
||||
bool willXPNeedDstCopy(const GrDrawTargetCaps& caps) const;
|
||||
|
||||
/**
|
||||
* The xfer processor factory.
|
||||
|
@ -55,9 +55,6 @@ 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.
|
||||
@ -79,20 +76,6 @@ public:
|
||||
// This should really only be used internally, base classes should return their own headers
|
||||
const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
|
||||
|
||||
// A struct to communicate descriptor information to the program descriptor builder
|
||||
struct DescInfo {
|
||||
bool operator==(const DescInfo& that) const {
|
||||
return fReadsDst == that.fReadsDst &&
|
||||
fReadsFragPosition == that.fReadsFragPosition;
|
||||
}
|
||||
bool operator!=(const DescInfo& that) const { return !(*this == that); };
|
||||
|
||||
// These flags give aggregated info on the processor stages that are used when building
|
||||
// programs.
|
||||
bool fReadsDst;
|
||||
bool fReadsFragPosition;
|
||||
};
|
||||
|
||||
private:
|
||||
template<typename T, size_t OFFSET> T* atOffset() {
|
||||
return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
|
||||
|
@ -142,7 +142,6 @@ 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 {}
|
||||
|
58
src/gpu/GrXferProcessor.cpp
Normal file
58
src/gpu/GrXferProcessor.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
|
@ -21,7 +21,15 @@ public:
|
||||
|
||||
~GrGLCoverageSetOpXP() SK_OVERRIDE {}
|
||||
|
||||
void emitCode(const EmitArgs& args) 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 {
|
||||
const GrCoverageSetOpXP& xp = args.fXP.cast<GrCoverageSetOpXP>();
|
||||
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
||||
|
||||
@ -32,16 +40,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
|
||||
void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
|
||||
|
||||
static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const GrCoverageSetOpXP& xp = processor.cast<GrCoverageSetOpXP>();
|
||||
uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
|
||||
b->add32(key);
|
||||
};
|
||||
|
||||
private:
|
||||
typedef GrGLXferProcessor INHERITED;
|
||||
};
|
||||
|
||||
@ -56,7 +56,7 @@ GrCoverageSetOpXP::GrCoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
|
||||
GrCoverageSetOpXP::~GrCoverageSetOpXP() {
|
||||
}
|
||||
|
||||
void GrCoverageSetOpXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
void GrCoverageSetOpXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
GrGLCoverageSetOpXP::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
@ -179,8 +179,10 @@ GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invert
|
||||
}
|
||||
}
|
||||
|
||||
GrXferProcessor* GrCoverageSetOpXPFactory::createXferProcessor(const GrProcOptInfo& /* colorPOI*/,
|
||||
const GrProcOptInfo& covPOI) const {
|
||||
GrXferProcessor*
|
||||
GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& covPOI,
|
||||
const GrDeviceCoordTexture* dstCopy) const {
|
||||
return GrCoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,6 @@ 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; }
|
||||
@ -48,6 +46,8 @@ public:
|
||||
private:
|
||||
GrCoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
|
||||
|
||||
void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
|
||||
const GrCoverageSetOpXP& xp = xpBase.cast<GrCoverageSetOpXP>();
|
||||
return (fRegionOp == xp.fRegionOp &&
|
||||
@ -66,9 +66,6 @@ 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;
|
||||
}
|
||||
@ -83,11 +80,15 @@ public:
|
||||
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
|
||||
|
||||
bool willReadDst() const SK_OVERRIDE { return false; }
|
||||
|
||||
private:
|
||||
GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
|
||||
|
||||
GrXferProcessor* onCreateXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
|
||||
|
||||
bool willReadDstColor() const SK_OVERRIDE { return false; }
|
||||
|
||||
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
|
||||
const GrCoverageSetOpXPFactory& xpf = xpfBase.cast<GrCoverageSetOpXPFactory>();
|
||||
return fRegionOp == xpf.fRegionOp;
|
||||
|
@ -499,7 +499,15 @@ public:
|
||||
GLCustomXP(const GrXferProcessor&) {}
|
||||
~GLCustomXP() SK_OVERRIDE {}
|
||||
|
||||
void emitCode(const EmitArgs& args) 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 {
|
||||
SkXfermode::Mode mode = args.fXP.cast<GrCustomXP>().mode();
|
||||
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
||||
const char* dstColor = fsBuilder->dstColor();
|
||||
@ -511,28 +519,20 @@ public:
|
||||
args.fInputCoverage, dstColor);
|
||||
}
|
||||
|
||||
void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
|
||||
void onSetData(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)
|
||||
: fMode(mode) {
|
||||
GrCustomXP::GrCustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy,
|
||||
bool willReadDstColor)
|
||||
: INHERITED(dstCopy, willReadDstColor), fMode(mode) {
|
||||
this->initClassID<GrCustomXP>();
|
||||
this->setWillReadDstColor();
|
||||
}
|
||||
|
||||
void GrCustomXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
void GrCustomXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
GLCustomXP::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define GrCustomXfermodePriv_DEFINED
|
||||
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrDrawTargetCaps.h"
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "GrTextureAccess.h"
|
||||
#include "GrXferProcessor.h"
|
||||
@ -57,11 +58,12 @@ private:
|
||||
|
||||
class GrCustomXP : public GrXferProcessor {
|
||||
public:
|
||||
static GrXferProcessor* Create(SkXfermode::Mode mode) {
|
||||
static GrXferProcessor* Create(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy,
|
||||
bool willReadDstColor) {
|
||||
if (!GrCustomXfermode::IsSupportedMode(mode)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return SkNEW_ARGS(GrCustomXP, (mode));
|
||||
return SkNEW_ARGS(GrCustomXP, (mode, dstCopy, willReadDstColor));
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,8 +71,6 @@ 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,7 +90,9 @@ public:
|
||||
SkXfermode::Mode mode() const { return fMode; }
|
||||
|
||||
private:
|
||||
GrCustomXP(SkXfermode::Mode mode);
|
||||
GrCustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy, bool willReadDstColor);
|
||||
|
||||
void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE;
|
||||
|
||||
@ -105,11 +107,6 @@ 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;
|
||||
}
|
||||
@ -126,9 +123,15 @@ public:
|
||||
void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
|
||||
|
||||
bool willReadDst() const SK_OVERRIDE { return true; }
|
||||
|
||||
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 onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
|
||||
const GrCustomXPFactory& xpf = xpfBase.cast<GrCustomXPFactory>();
|
||||
return fMode == xpf.fMode;
|
||||
|
@ -17,7 +17,10 @@ public:
|
||||
|
||||
~GrGLDisableColorXP() SK_OVERRIDE {}
|
||||
|
||||
void emitCode(const EmitArgs& args) SK_OVERRIDE {
|
||||
static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
|
||||
|
||||
private:
|
||||
void onEmitCode(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.
|
||||
@ -25,11 +28,8 @@ public:
|
||||
fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary);
|
||||
}
|
||||
|
||||
void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
|
||||
void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
|
||||
|
||||
static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
|
||||
|
||||
private:
|
||||
typedef GrGLXferProcessor INHERITED;
|
||||
};
|
||||
|
||||
@ -39,7 +39,7 @@ GrDisableColorXP::GrDisableColorXP() {
|
||||
this->initClassID<GrDisableColorXP>();
|
||||
}
|
||||
|
||||
void GrDisableColorXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
void GrDisableColorXP::onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
GrGLDisableColorXP::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
@ -57,8 +57,10 @@ GrDisableColorXPFactory::GrDisableColorXPFactory() {
|
||||
this->initClassID<GrDisableColorXPFactory>();
|
||||
}
|
||||
|
||||
GrXferProcessor* GrDisableColorXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& covPOI) const {
|
||||
GrXferProcessor*
|
||||
GrDisableColorXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& covPOI,
|
||||
const GrDeviceCoordTexture* dstCopy) const {
|
||||
return GrDisableColorXP::Create();
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ 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; }
|
||||
@ -46,6 +44,8 @@ public:
|
||||
private:
|
||||
GrDisableColorXP();
|
||||
|
||||
void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
@ -61,9 +61,6 @@ 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;
|
||||
}
|
||||
@ -81,11 +78,15 @@ 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;
|
||||
}
|
||||
|
@ -38,7 +38,15 @@ public:
|
||||
|
||||
virtual ~GrGLPorterDuffXferProcessor() {}
|
||||
|
||||
void emitCode(const EmitArgs& args) 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:
|
||||
void onEmitCode(const EmitArgs& args) SK_OVERRIDE {
|
||||
const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProcessor>();
|
||||
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
||||
if (xp.hasSecondaryOutput()) {
|
||||
@ -80,23 +88,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
|
||||
void onSetData(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)
|
||||
GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend,
|
||||
GrBlendCoeff dstBlend,
|
||||
GrColor constant,
|
||||
const GrDeviceCoordTexture* dstCopy,
|
||||
bool willReadDstColor)
|
||||
: fSrcBlend(srcBlend)
|
||||
, fDstBlend(dstBlend)
|
||||
, fBlendConstant(constant)
|
||||
@ -108,8 +111,8 @@ GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl
|
||||
GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() {
|
||||
}
|
||||
|
||||
void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
void GrPorterDuffXferProcessor::onGetGLProcessorKey(const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
GrGLPorterDuffXferProcessor::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
@ -353,16 +356,20 @@ GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) {
|
||||
}
|
||||
}
|
||||
|
||||
GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& covPOI) const {
|
||||
GrXferProcessor*
|
||||
GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& covPOI,
|
||||
const GrDeviceCoordTexture* dstCopy) const {
|
||||
if (!covPOI.isFourChannelOutput()) {
|
||||
return GrPorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff);
|
||||
return GrPorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy,
|
||||
this->willReadDstColor());
|
||||
} 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);
|
||||
blendConstant, dstCopy,
|
||||
this->willReadDstColor());
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
@ -484,6 +491,10 @@ 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,
|
||||
|
@ -1451,10 +1451,8 @@ 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, descInfo, this,
|
||||
batchTracker)) {
|
||||
if (!GrGLProgramDescBuilder::Build(desc, primProc, pipeline, this, batchTracker)) {
|
||||
SkDEBUGFAIL("Failed to generate GL program descriptor");
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ public:
|
||||
void buildProgramDesc(GrProgramDesc*,
|
||||
const GrPrimitiveProcessor&,
|
||||
const GrPipeline&,
|
||||
const GrProgramDesc::DescInfo&,
|
||||
const GrBatchTracker&) const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
@ -61,10 +61,6 @@ 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);
|
||||
@ -107,38 +103,15 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline
|
||||
const GrBatchTracker& batchTracker) {
|
||||
this->setRenderTargetState(primProc, pipeline);
|
||||
|
||||
const GrDeviceCoordTexture* dstCopy = pipeline.getDstCopy();
|
||||
if (dstCopy) {
|
||||
if (fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid()) {
|
||||
fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyTopLeftUni,
|
||||
static_cast<GrGLfloat>(dstCopy->offset().fX),
|
||||
static_cast<GrGLfloat>(dstCopy->offset().fY));
|
||||
fProgramDataManager.set2f(fBuiltinUniformHandles.fDstCopyScaleUni,
|
||||
1.f / dstCopy->texture()->width(),
|
||||
1.f / dstCopy->texture()->height());
|
||||
GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
|
||||
static GrTextureParams kParams; // the default is clamp, nearest filtering.
|
||||
fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
|
||||
} else {
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
|
||||
}
|
||||
} else {
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopyTopLeftUni.isValid());
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopyScaleUni.isValid());
|
||||
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
|
||||
}
|
||||
|
||||
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
|
||||
// of GLProgram determine how to set coord transforms
|
||||
fGeometryProcessor->fGLProc->setData(fProgramDataManager, primProc, batchTracker);
|
||||
this->bindTextures(fGeometryProcessor.get(), primProc);
|
||||
|
||||
if (fXferProcessor.get()) {
|
||||
const GrXferProcessor& xp = *pipeline.getXferProcessor();
|
||||
fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
|
||||
this->bindTextures(fXferProcessor.get(), xp);
|
||||
}
|
||||
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
|
||||
|
@ -89,7 +89,6 @@ 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
|
||||
@ -135,21 +134,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
// make sure any padding in the header is zeroed.
|
||||
memset(header, 0, kHeaderSize);
|
||||
|
||||
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) {
|
||||
if (pipeline.readsFragPosition()) {
|
||||
header->fFragPosKey =
|
||||
GrGLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget(),
|
||||
gpu->glCaps());
|
||||
|
@ -47,8 +47,6 @@ 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
|
||||
@ -58,7 +56,6 @@ public:
|
||||
static bool Build(GrProgramDesc*,
|
||||
const GrPrimitiveProcessor&,
|
||||
const GrPipeline&,
|
||||
const GrProgramDesc::DescInfo&,
|
||||
const GrGLGpu*,
|
||||
const GrBatchTracker&);
|
||||
};
|
||||
|
69
src/gpu/gl/GrGLXferProcessor.cpp
Normal file
69
src/gpu/gl/GrGLXferProcessor.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "GrGLProcessor.h"
|
||||
|
||||
class GrGLXPBuilder;
|
||||
class GrXferProcessor;
|
||||
|
||||
class GrGLXferProcessor {
|
||||
public:
|
||||
@ -46,16 +47,25 @@ 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.
|
||||
*/
|
||||
virtual void emitCode(const EmitArgs&) = 0;
|
||||
void emitCode(const EmitArgs&);
|
||||
|
||||
/** 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. */
|
||||
virtual void setData(const GrGLProgramDataManager&,
|
||||
const GrXferProcessor&) = 0;
|
||||
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);
|
||||
|
||||
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
|
||||
|
@ -179,56 +179,9 @@ const char* GrGLFragmentShaderBuilder::dstColor() {
|
||||
fbFetchColorName = declared_color_output_name();
|
||||
}
|
||||
return fbFetchColorName;
|
||||
} else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
|
||||
} else {
|
||||
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() {
|
||||
|
@ -97,7 +97,6 @@ public:
|
||||
|
||||
private:
|
||||
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
|
||||
void emitCodeToReadDstTexture();
|
||||
void enableCustomOutput();
|
||||
void enableSecondaryOutput();
|
||||
const char* getPrimaryColorOutputName() const;
|
||||
|
@ -56,12 +56,6 @@ 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;
|
||||
|
@ -267,11 +267,6 @@ 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:
|
||||
|
@ -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, pipeline.descInfo(), bt);
|
||||
gpu->buildProgramDesc(&desc, *primProc, pipeline, bt);
|
||||
|
||||
GrGpu::DrawArgs args(primProc, &pipeline, &desc, &bt);
|
||||
SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(args, gpu));
|
||||
|
Loading…
Reference in New Issue
Block a user