#reed
modecolorfilters
-#egdaniel
-xfermodes3
-mixed_xfermodes
-
#humper skia:2049
dashcubics
const GrDrawTargetCaps&, \
GrTexture* dummyTextures[2])
-#define GR_DECLARE_XP_FACTORY_TEST \
- static GrProcessorTestFactory<GrXPFactory> gTestFactory SK_UNUSED; \
- static GrXPFactory* TestCreate(SkRandom*, \
- GrContext*, \
- const GrDrawTargetCaps&, \
- GrTexture* dummyTextures[2])
-
-
/** GrProcessor subclasses should insert this macro in their implementation file. They must then
* also implement this static function:
* GrProcessor* TestCreate(SkRandom*,
#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Effect) \
GrProcessorTestFactory<GrFragmentProcessor> Effect :: gTestFactory(Effect :: TestCreate)
-#define GR_DEFINE_XP_FACTORY_TEST(Factory) \
- GrProcessorTestFactory<GrXPFactory> Factory :: gTestFactory(Factory :: TestCreate)
-
#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(Effect) \
GrProcessorTestFactory<GrGeometryProcessor> Effect :: gTestFactory(Effect :: TestCreate)
// its definitions will compile.
#define GR_DECLARE_FRAGMENT_PROCESSOR_TEST \
static GrFragmentProcessor* TestCreate(SkRandom*, \
- GrContext*, \
- const GrDrawTargetCaps&, \
- GrTexture* dummyTextures[2])
+ GrContext*, \
+ const GrDrawTargetCaps&, \
+ GrTexture* dummyTextures[2])
#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(X)
-// The unit test relies on static initializers. Just declare the TestCreate function so that
-// its definitions will compile.
-#define GR_DECLARE_XP_FACTORY_TEST \
- static GrXPFactory* TestCreate(SkRandom*, \
- GrContext*, \
- const GrDrawTargetCaps&, \
- GrTexture* dummyTextures[2])
-#define GR_DEFINE_XP_FACTORY_TEST(X)
-
// The unit test relies on static initializers. Just declare the TestCreate function so that
// its definitions will compile.
#define GR_DECLARE_GEOMETRY_PROCESSOR_TEST \
static GrGeometryProcessor* TestCreate(SkRandom*, \
- GrContext*, \
- const GrDrawTargetCaps&, \
- GrTexture* dummyTextures[2])
+ GrContext*, \
+ const GrDrawTargetCaps&, \
+ GrTexture* dummyTextures[2])
#define GR_DEFINE_GEOMETRY_PROCESSOR_TEST(X)
#endif // !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
#define GrXferProcessor_DEFINED
#include "GrColor.h"
-#include "GrProcessor.h"
+#include "GrFragmentProcessor.h"
#include "GrTypes.h"
#include "SkXfermode.h"
-class GrDrawTargetCaps;
-class GrGLCaps;
-class GrGLXferProcessor;
class GrProcOptInfo;
/**
* A GrXferProcessor is never installed directly into our draw state, but instead is created from a
* GrXPFactory once we have finalized the state of our draw.
*/
-class GrXferProcessor : public GrProcessor {
+class GrXferProcessor : public GrFragmentProcessor {
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;
-
- /** Returns a new instance of the appropriate *GL* implementation class
- for the given GrXferProcessor; caller is responsible for deleting
- the object. */
- virtual GrGLXferProcessor* createGLInstance() const = 0;
-
/**
* Optimizations for blending / coverage that an OptDrawState should apply to itself.
*/
bool colorWriteDisabled,
bool doesStencilWrite,
GrColor* color,
- uint8_t* coverage,
- const GrDrawTargetCaps& caps) = 0;
+ uint8_t* coverage) = 0;
struct BlendInfo {
GrBlendCoeff fSrcBlend;
/** Will this prceossor read the destination pixel value? */
bool willReadDstColor() const { return fWillReadDstColor; }
- /**
- * Returns whether or not this xferProcossor will set a secondary output to be used with dual
- * source blending.
- */
- virtual bool hasSecondaryOutput() const { return false; }
-
- /** Returns true if this and other processor conservatively draw identically. It can only return
- true when the two processor are of the same subclass (i.e. they return the same object from
- from getFactory()).
-
- A return value of true from isEqual() should not be used to test whether the processor would
- generate the same shader code. To test for identical code generation use getGLProcessorKey*/
-
- bool isEqual(const GrXferProcessor& that) const {
- if (this->classID() != that.classID()) {
- return false;
- }
- return this->onIsEqual(that);
- }
-
-
protected:
GrXferProcessor() : fWillReadDstColor(false) {}
void setWillReadDstColor() { fWillReadDstColor = true; }
private:
- virtual bool onIsEqual(const GrXferProcessor&) const = 0;
bool fWillReadDstColor;
virtual const char* name() const { return "Porter Duff"; }
- void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
-
- GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
-
- virtual bool hasSecondaryOutput() const SK_OVERRIDE;
-
- ///////////////////////////////////////////////////////////////////////////
- /// @name Stage Output Types
- ////
-
- enum SecondaryOutputType {
- // There is no secondary output
- kNone_SecondaryOutputType,
- // Writes coverage as the secondary output. Only set if dual source blending is supported
- // and primary output is kModulate.
- kCoverage_SecondaryOutputType,
- // Writes coverage * (1 - colorA) as the secondary output. Only set if dual source blending
- // is supported and primary output is kModulate.
- kCoverageISA_SecondaryOutputType,
- // Writes coverage * (1 - colorRGBA) as the secondary output. Only set if dual source
- // blending is supported and primary output is kModulate.
- kCoverageISC_SecondaryOutputType,
-
- kSecondaryOutputTypeCnt,
- };
-
- SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputType; }
-
- GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- bool isCoverageDrawing,
- bool colorWriteDisabled,
- bool doesStencilWrite,
- GrColor* color,
- uint8_t* coverage,
- const GrDrawTargetCaps& caps) SK_OVERRIDE;
-
- void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE {
+ virtual void getGLProcessorKey(const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
+ virtual GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
+
+ virtual GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI,
+ bool isCoverageDrawing,
+ bool colorWriteDisabled,
+ bool doesStencilWrite,
+ GrColor* color,
+ uint8_t* coverage) SK_OVERRIDE;
+
+ virtual void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE {
blendInfo->fSrcBlend = fSrcBlend;
blendInfo->fDstBlend = fDstBlend;
blendInfo->fBlendConstant = fBlendConstant;
private:
GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant);
- bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
- const GrPorterDuffXferProcessor& xp = xpBase.cast<GrPorterDuffXferProcessor>();
+ virtual bool onIsEqual(const GrFragmentProcessor& fpBase) const SK_OVERRIDE {
+ const GrPorterDuffXferProcessor& xp = fpBase.cast<GrPorterDuffXferProcessor>();
if (fSrcBlend != xp.fSrcBlend ||
fDstBlend != xp.fDstBlend ||
- fBlendConstant != xp.fBlendConstant ||
- fSecondaryOutputType != xp.fSecondaryOutputType) {
+ fBlendConstant != xp.fBlendConstant) {
return false;
}
return true;
}
- void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
-
- GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- bool isCoverageDrawing,
- bool colorWriteDisabled,
- bool doesStencilWrite,
- GrColor* color,
- uint8_t* coverage);
-
- void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrDrawTargetCaps& caps,
- bool isCoverageDrawing, bool readDst);
+ virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
GrBlendCoeff fSrcBlend;
GrBlendCoeff fDstBlend;
GrColor fBlendConstant;
- SecondaryOutputType fSecondaryOutputType;
typedef GrXferProcessor INHERITED;
};
return (fSrcCoeff == xpf.fSrcCoeff && fDstCoeff == xpf.fDstCoeff);
}
- GR_DECLARE_XP_FACTORY_TEST;
-
GrBlendCoeff fSrcCoeff;
GrBlendCoeff fDstCoeff;
virtual const char* name() const = 0;
- /**
- * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
- * processor's GL backend implementation.
- */
+ /** Implemented using GLProcessor::GenKey as described in this class's comment. */
virtual void getGLProcessorKey(const GrBatchTracker& bt,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) const = 0;
drawState.isColorWriteDisabled(),
drawState.getStencil().doesWrite(),
&fColor,
- &fCoverage,
- caps);
+ &fCoverage);
}
// When path rendering the stencil settings are not always set on the draw state
init.fCoverage = this->getCoverage();
fGeometryProcessor->initBatchTracker(&fBatchTracker, init);
}
+
+ this->setOutputStateInfo(drawState, coverageColor, optFlags, caps);
+}
+
+void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
+ GrColor coverage,
+ GrXferProcessor::OptFlags optFlags,
+ const GrDrawTargetCaps& caps) {
+ // Set this default and then possibly change our mind if there is coverage.
+ fDescInfo.fPrimaryOutputType = GrProgramDesc::kModulate_PrimaryOutputType;
+ fDescInfo.fSecondaryOutputType = GrProgramDesc::kNone_SecondaryOutputType;
+
+ // Determine whether we should use dual source blending or shader code to keep coverage
+ // separate from color.
+ bool keepCoverageSeparate = !(optFlags & GrXferProcessor::kSetCoverageDrawing_OptFlag);
+ if (keepCoverageSeparate && !ds.hasSolidCoverage(coverage)) {
+ if (caps.dualSourceBlendingSupport()) {
+ if (kZero_GrBlendCoeff == fDstBlend) {
+ // write the coverage value to second color
+ fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverage_SecondaryOutputType;
+ fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
+ } else if (kSA_GrBlendCoeff == fDstBlend) {
+ // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
+ fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISA_SecondaryOutputType;
+ fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
+ } else if (kSC_GrBlendCoeff == fDstBlend) {
+ // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
+ fDescInfo.fSecondaryOutputType = GrProgramDesc::kCoverageISC_SecondaryOutputType;
+ fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
+ }
+ } else if (fDescInfo.fReadsDst &&
+ kOne_GrBlendCoeff == fSrcBlend &&
+ kZero_GrBlendCoeff == fDstBlend) {
+ fDescInfo.fPrimaryOutputType = GrProgramDesc::kCombineWithDst_PrimaryOutputType;
+ }
+ }
}
void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
return false;
}
- if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) {
- return false;
- }
-
// The program desc comparison should have already assured that the stage counts match.
SkASSERT(this->numFragmentStages() == that.numFragmentStages());
for (int i = 0; i < this->numFragmentStages(); i++) {
int numCoverageStages() const { return fFragmentStages.count() - fNumColorStages; }
int numFragmentStages() const { return fFragmentStages.count(); }
int numTotalStages() const {
- // the + 1 at the end is for the xferProcessor which will always be present
- return this->numFragmentStages() + (this->hasGeometryProcessor() ? 1 : 0) + 1;
+ return this->numFragmentStages() + (this->hasGeometryProcessor() ? 1 : 0);
}
bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
}
template<>
-SkTArray<GrProcessorTestFactory<GrXPFactory>*, true>*
-GrProcessorTestFactory<GrXPFactory>::GetFactories() {
- static SkTArray<GrProcessorTestFactory<GrXPFactory>*, true> gFactories;
+SkTArray<GrProcessorTestFactory<GrXferProcessor>*, true>*
+GrProcessorTestFactory<GrXferProcessor>::GetFactories() {
+ static SkTArray<GrProcessorTestFactory<GrXferProcessor>*, true> gFactories;
return &gFactories;
}
*/
static const int kFPFactoryCount = 37;
static const int kGPFactoryCount = 14;
-static const int kXPFactoryCount = 1;
+static const int kXPFactoryCount = 0;
template<>
void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
}
template<>
-void GrProcessorTestFactory<GrXPFactory>::VerifyFactoryCount() {
+void GrProcessorTestFactory<GrXferProcessor>::VerifyFactoryCount() {
if (kXPFactoryCount != GetFactories()->count()) {
- SkFAIL("Wrong number of xp factory factories!");
+ SkFAIL("Wrong number of xfer processor factories!");
}
}
}
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Stage Output Types
+ ////
+
+ enum PrimaryOutputType {
+ // Modulate color and coverage, write result as the color output.
+ kModulate_PrimaryOutputType,
+ // Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
+ // can only be set if fDstReadKey is non-zero.
+ kCombineWithDst_PrimaryOutputType,
+
+ kPrimaryOutputTypeCnt,
+ };
+
+ enum SecondaryOutputType {
+ // There is no secondary output
+ kNone_SecondaryOutputType,
+ // Writes coverage as the secondary output. Only set if dual source blending is supported
+ // and primary output is kModulate.
+ kCoverage_SecondaryOutputType,
+ // Writes coverage * (1 - colorA) as the secondary output. Only set if dual source blending
+ // is supported and primary output is kModulate.
+ kCoverageISA_SecondaryOutputType,
+ // Writes coverage * (1 - colorRGBA) as the secondary output. Only set if dual source
+ // blending is supported and primary output is kModulate.
+ kCoverageISC_SecondaryOutputType,
+
+ kSecondaryOutputTypeCnt,
+ };
+
// Specifies where the initial color comes from before the stages are applied.
enum ColorInput {
kAllOnes_ColorInput,
ColorInput fColorInput : 8;
ColorInput fCoverageInput : 8;
+ PrimaryOutputType fPrimaryOutputType : 8;
+ SecondaryOutputType fSecondaryOutputType : 8;
+
SkBool8 fHasGeometryProcessor;
int8_t fColorEffectCnt;
int8_t fCoverageEffectCnt;
fInputCoverageIsUsed == that.fInputCoverageIsUsed &&
fReadsDst == that.fReadsDst &&
fReadsFragPosition == that.fReadsFragPosition &&
- fRequiresLocalCoordAttrib == that.fRequiresLocalCoordAttrib;
+ fRequiresLocalCoordAttrib == that.fRequiresLocalCoordAttrib &&
+ fPrimaryOutputType == that.fPrimaryOutputType &&
+ fSecondaryOutputType == that.fSecondaryOutputType;
+
}
bool operator!=(const DescInfo& that) const { return !(*this == that); };
// TODO when GPs control uniform / attribute handling of color / coverage, then we can
bool fReadsFragPosition;
bool fRequiresLocalCoordAttrib;
+ // Fragment shader color outputs
+ GrProgramDesc::PrimaryOutputType fPrimaryOutputType : 8;
+ GrProgramDesc::SecondaryOutputType fSecondaryOutputType : 8;
};
private:
#include "GrBlend.h"
#include "GrDrawState.h"
-#include "GrDrawTargetCaps.h"
#include "GrInvariantOutput.h"
#include "GrProcessor.h"
#include "GrTypes.h"
#include "GrXferProcessor.h"
-#include "gl/GrGLXferProcessor.h"
+#include "gl/GrGLProcessor.h"
#include "gl/builders/GrGLFragmentShaderBuilder.h"
#include "gl/builders/GrGLProgramBuilder.h"
virtual ~GrGLPorterDuffXferProcessor() {}
- virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
- const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProcessor>();
- GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
- if (xp.hasSecondaryOutput()) {
- switch(xp.secondaryOutputType()) {
- case GrPorterDuffXferProcessor::kCoverage_SecondaryOutputType:
- fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, args.fInputCoverage);
- break;
- case GrPorterDuffXferProcessor::kCoverageISA_SecondaryOutputType:
- fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;",
- args.fOutputSecondary, args.fInputColor,
- args.fInputCoverage);
- break;
- case GrPorterDuffXferProcessor::kCoverageISC_SecondaryOutputType:
- fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;",
- args.fOutputSecondary, args.fInputColor,
- args.fInputCoverage);
- break;
- default:
- SkFAIL("Unexpected Secondary Output");
- }
- }
-
- fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
- args.fInputCoverage);
+ virtual void emitCode(GrGLFPBuilder* builder,
+ const GrFragmentProcessor& fp,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) SK_OVERRIDE {
+ GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor);
}
- virtual void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
+ virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {};
- static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) {
- const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferProcessor>();
- b->add32(xp.secondaryOutputType());
- };
+ static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b) {};
private:
typedef GrGLXferProcessor INHERITED;
GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend,
GrColor constant)
- : fSrcBlend(srcBlend)
- , fDstBlend(dstBlend)
- , fBlendConstant(constant)
- , fSecondaryOutputType(kNone_SecondaryOutputType) {
+ : fSrcBlend(srcBlend), fDstBlend(dstBlend), fBlendConstant(constant) {
this->initClassID<GrPorterDuffXferProcessor>();
}
GrGLPorterDuffXferProcessor::GenKey(*this, caps, b);
}
-GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const {
+GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const {
return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this));
}
bool isCoverageDrawing,
bool colorWriteDisabled,
bool doesStencilWrite,
- GrColor* color, uint8_t* coverage,
- const GrDrawTargetCaps& caps) {
- GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI,
- coveragePOI,
- isCoverageDrawing,
- colorWriteDisabled,
- doesStencilWrite,
- color,
- coverage);
-
- this->calcOutputTypes(optFlags, caps, isCoverageDrawing,
- colorPOI.readsDst() || coveragePOI.readsDst());
- return optFlags;
-}
-
-void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags,
- const GrDrawTargetCaps& caps,
- bool isCoverageDrawing, bool readsDst) {
- // If we do have coverage determine whether it matters. Dual source blending is expensive so
- // we don't do it if we are doing coverage drawing. If we aren't then We always do dual source
- // blending if we have any effective coverage stages OR the geometry processor doesn't emits
- // solid coverage.
- if (!(optFlags & kSetCoverageDrawing_OptFlag) && !isCoverageDrawing) {
- if (caps.dualSourceBlendingSupport()) {
- if (kZero_GrBlendCoeff == fDstBlend) {
- // write the coverage value to second color
- fSecondaryOutputType = kCoverage_SecondaryOutputType;
- fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
- } else if (kSA_GrBlendCoeff == fDstBlend) {
- // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
- fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
- fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
- } else if (kSC_GrBlendCoeff == fDstBlend) {
- // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
- fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
- fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
- }
- }
- }
-}
-
-GrXferProcessor::OptFlags
-GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI,
- const GrProcOptInfo& coveragePOI,
- bool isCoverageDrawing,
- bool colorWriteDisabled,
- bool doesStencilWrite,
- GrColor* color, uint8_t* coverage) {
+ GrColor* color, uint8_t* coverage) {
if (colorWriteDisabled) {
fSrcBlend = kZero_GrBlendCoeff;
fDstBlend = kOne_GrBlendCoeff;
return GrXferProcessor::kNone_Opt;
}
-
-bool GrPorterDuffXferProcessor::hasSecondaryOutput() const {
- return kNone_SecondaryOutputType != fSecondaryOutputType;
-}
-
///////////////////////////////////////////////////////////////////////////////
GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst)
return opaque;
}
-GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
-
-GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
- GrContext*,
- const GrDrawTargetCaps&,
- GrTexture*[]) {
- GrBlendCoeff src;
- do {
- src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
- } while (GrBlendCoeffRefsSrc(src));
-
- GrBlendCoeff dst;
- do {
- dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
- } while (GrBlendCoeffRefsDst(dst));
-
- return GrPorterDuffXPFactory::Create(src, dst);
-}
typedef GrGLProcessor INHERITED;
};
+class GrGLXferProcessor : public GrGLFragmentProcessor {
+public:
+ GrGLXferProcessor() {}
+
+ virtual ~GrGLXferProcessor() {}
+
+private:
+ typedef GrGLFragmentProcessor INHERITED;
+};
+
#endif
#include "GrCoordTransform.h"
#include "GrGLGeometryProcessor.h"
#include "GrGLProcessor.h"
-#include "GrGLXferProcessor.h"
#include "GrGpuGL.h"
#include "GrGLPathRendering.h"
#include "GrGLShaderVar.h"
#include "GrGLSL.h"
#include "GrOptDrawState.h"
-#include "GrXferProcessor.h"
#include "SkXfermode.h"
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledGeoProc* geometryProcessor,
- GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
: fColor(GrColor_ILLEGAL)
, fCoverage(0)
, fBuiltinUniformHandles(builtinUniforms)
, fProgramID(programID)
, fGeometryProcessor(geometryProcessor)
- , fXferProcessor(xferProcessor)
, fFragmentProcessors(SkRef(fragmentProcessors))
, fDesc(desc)
, fGpu(gpu)
if (fGeometryProcessor.get()) {
this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
}
- if (fXferProcessor.get()) {
- this->initSamplers(fXferProcessor.get(), &texUnitIdx);
- }
int numProcs = fFragmentProcessors->fProcs.count();
for (int i = 0; i < numProcs; i++) {
this->initSamplers(fFragmentProcessors->fProcs[i], &texUnitIdx);
fGeometryProcessor->fGLProc->setData(fProgramDataManager, gp, bt);
this->bindTextures(fGeometryProcessor, gp);
}
- if (fXferProcessor.get()) {
- const GrXferProcessor& xp = *optState.getXferProcessor();
- fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
- this->bindTextures(fXferProcessor, xp);
- }
this->setFragmentData(optState);
// Some of GrGLProgram subclasses need to update state here
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
- GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL,
- xferProcessor, fragmentProcessors) {
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, fragmentProcessors) {
}
void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(const GrOptDrawState& optState) {
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
- GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
const SeparableVaryingInfoArray& separableVaryings)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms,
- xferProcessor, fragmentProcessors) {
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fragmentProcessors) {
int count = separableVaryings.count();
fVaryings.push_back_n(count);
for (int i = 0; i < count; i++) {
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
- GrGLInstalledXferProc* xp,
GrGLInstalledFragProcs* fps,
int texCoordSetCnt)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, xp, fps)
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fps)
, fTexCoordSetCnt(texCoordSetCnt) {
}
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledGeoProc* geometryProcessor,
- GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
// Sets the texture units for samplers.
// the installed effects
SkAutoTDelete<GrGLInstalledGeoProc> fGeometryProcessor;
- SkAutoTDelete<GrGLInstalledXferProc> fXferProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
GrProgramDesc fDesc;
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
virtual void onSetMatrixAndRenderTargetHeight(const GrOptDrawState&);
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
const SeparableVaryingInfoArray& separableVaryings);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledXferProc* xp,
- GrGLInstalledFragProcs* fps,
+ GrGLInstalledFragProcs* fragmentProcessors,
int texCoordSetCnt);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
virtual void setTransformData(const GrPendingFragmentStage&,
const GrFragmentProcessor& fp = *fps.getProcessor();
GrProcessorKeyBuilder b(&desc->fKey);
fp.getGLProcessorKey(gpu->glCaps(), &b);
- if (!get_meta_key(fp, gpu->glCaps(),
- gen_transform_key(fps, requiresLocalCoordAttrib), 0, &b)) {
+ if (!get_meta_key(*fps.getProcessor(), gpu->glCaps(),
+ gen_transform_key(fps, requiresLocalCoordAttrib), 0, &b)) {
desc->fKey.reset();
return false;
}
}
- const GrXferProcessor& xp = *optState.getXferProcessor();
- GrProcessorKeyBuilder b(&desc->fKey);
- xp.getGLProcessorKey(gpu->glCaps(), &b);
- if (!get_meta_key(xp, gpu->glCaps(), 0, 0, &b)) {
- desc->fKey.reset();
- return false;
- }
-
// --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
// Because header is a pointer into the dynamic array, we can't push any new data into the key
// below here.
header->fFragPosKey = 0;
}
+ header->fPrimaryOutputType = descInfo.fPrimaryOutputType;
+ header->fSecondaryOutputType = descInfo.fSecondaryOutputType;
+
header->fColorEffectCnt = optState.numColorStages();
header->fCoverageEffectCnt = optState.numCoverageStages();
desc->finalize();
+++ /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.
- */
-
-#ifndef GrGLXferProcessor_DEFINED
-#define GrGLXferProcessor_DEFINED
-
-#include "GrGLProcessor.h"
-
-class GrGLXPBuilder;
-
-class GrGLXferProcessor {
-public:
- GrGLXferProcessor() {}
- virtual ~GrGLXferProcessor() {}
-
- typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
- struct EmitArgs {
- EmitArgs(GrGLXPBuilder* pb,
- const GrXferProcessor& xp,
- const char* inputColor,
- const char* inputCoverage,
- const char* outputPrimary,
- const char* outputSecondary,
- const TextureSamplerArray& samplers)
- : fPB(pb)
- , fXP(xp)
- , fInputColor(inputColor)
- , fInputCoverage(inputCoverage)
- , fOutputPrimary(outputPrimary)
- , fOutputSecondary(outputSecondary)
- , fSamplers(samplers) {}
-
- GrGLXPBuilder* fPB;
- const GrXferProcessor& fXP;
- const char* fInputColor;
- const char* fInputCoverage;
- const char* fOutputPrimary;
- const char* fOutputSecondary;
- const TextureSamplerArray& fSamplers;
- };
- /**
- * 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;
-
- /** 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;
-private:
- typedef GrGLProcessor INHERITED;
-};
-#endif
return dual_source_output_name();
}
+void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputColor,
+ const GrGLSLExpr4& inputCoverage) {
+ this->enableSecondaryOutput();
+ const char* secondaryOutputName = this->getSecondaryColorOutputName();
+ GrGLSLExpr4 coeff(1);
+ switch (fProgramBuilder->header().fSecondaryOutputType) {
+ case GrProgramDesc::kCoverage_SecondaryOutputType:
+ break;
+ case GrProgramDesc::kCoverageISA_SecondaryOutputType:
+ // Get (1-A) into coeff
+ coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
+ break;
+ case GrProgramDesc::kCoverageISC_SecondaryOutputType:
+ // Get (1-RGBA) into coeff
+ coeff = GrGLSLExpr4(1) - inputColor;
+ break;
+ default:
+ SkFAIL("Unexpected Secondary Output");
+ }
+ // Get coeff * coverage into modulate and then write that to the dual source output.
+ this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
+}
+
+void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& inputColor,
+ const GrGLSLExpr4& inputCoverage) {
+ GrGLSLExpr4 fragColor = inputColor * inputCoverage;
+ switch (fProgramBuilder->header().fPrimaryOutputType) {
+ case GrProgramDesc::kModulate_PrimaryOutputType:
+ break;
+ case GrProgramDesc::kCombineWithDst_PrimaryOutputType:
+ {
+ // Tack on "+(1-coverage)dst onto the frag color.
+ GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
+ GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor());
+ fragColor = fragColor + dstContribution;
+ }
+ break;
+ default:
+ SkFAIL("Unknown Primary Output");
+ }
+
+ // On any post 1.10 GLSL supporting GPU, we declare custom output
+ if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) {
+ this->enableCustomOutput();
+ }
+
+ this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragColor.c_str());
+}
+
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
GrGpuGL* gpu = fProgramBuilder->gpu();
void enableSecondaryOutput();
const char* getPrimaryColorOutputName() const;
const char* getSecondaryColorOutputName() const;
+ void enableSecondaryOutput(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
+ void combineColorAndCoverage(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
void bindFragmentShaderLocations(GrGLuint programID);
GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fXferProcessor, fFragmentProcessors.get(),
- fTexCoordSetCnt));
+ fFragmentProcessors.get(), fTexCoordSetCnt));
}
// building
this->resolveSeparableVaryings(programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fXferProcessor, fFragmentProcessors.get(),
- fSeparableVaryingInfos));
+ fFragmentProcessors.get(), fSeparableVaryingInfos));
}
#include "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h"
-#include "../GrGLXferProcessor.h"
#include "../GrGpuGL.h"
#include "GrCoordTransform.h"
#include "GrGLLegacyNvprProgramBuilder.h"
pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4);
+ // write the secondary color output if necessary
+ if (GrProgramDesc::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
+ pb->fFS.enableSecondaryOutput(inputColor, inputCoverageVec4);
+ }
+
+ pb->fFS.combineColorAndCoverage(inputColor, inputCoverageVec4);
+
return pb->finalize();
}
-GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState,
- bool hasGeometryProcessor,
- GrGpuGL* gpu) {
+GrGLProgramBuilder*
+GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawState& optState,
+ bool hasGeometryProcessor,
+ GrGpuGL* gpu) {
const GrProgramDesc& desc = optState.programDesc();
if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) {
SkASSERT(gpu->glCaps().pathRenderingSupport());
, fOutOfStage(true)
, fStageIndex(-1)
, fGeometryProcessor(NULL)
- , fXferProcessor(NULL)
, fOptState(optState)
, fDesc(optState.programDesc())
, fGpu(gpu)
if (fOptState.hasGeometryProcessor()) {
fVS.transformToNormalizedDeviceSpace();
}
-
- this->emitAndInstallXferProc(*fOptState.getXferProcessor(), *inputColor, *inputCoverage);
}
void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
verify(gp);
}
-void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
- const GrGLSLExpr4& colorIn,
- const GrGLSLExpr4& coverageIn) {
- // Program builders have a bit of state we need to clear with each effect
- AutoStageAdvance adv(this);
-
- SkASSERT(!fXferProcessor);
- fXferProcessor = SkNEW(GrGLInstalledXferProc);
-
- fXferProcessor->fGLProc.reset(xp.createGLInstance());
-
- // Enable dual source secondary output if we have one
- if (xp.hasSecondaryOutput()) {
- fFS.enableSecondaryOutput();
- }
-
- // On any post 1.10 GLSL supporting GPU, we declare custom output
- if (k110_GrGLSLGeneration != fFS.fProgramBuilder->gpu()->glslGeneration()) {
- fFS.enableCustomOutput();
- }
-
- SkString openBrace;
- openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
- fFS.codeAppend(openBrace.c_str());
-
- SkSTArray<4, GrGLProcessor::TextureSampler> samplers(xp.numTextures());
- this->emitSamplers(xp, &samplers, fXferProcessor);
-
- GrGLXferProcessor::EmitArgs args(this, xp, colorIn.c_str(), coverageIn.c_str(),
- fFS.getPrimaryColorOutputName(),
- fFS.getSecondaryColorOutputName(), samplers);
- fXferProcessor->fGLProc->emitCode(args);
-
- // We have to check that effects and the code they emit are consistent, ie if an effect
- // asks for dst color, then the emit code needs to follow suit
- verify(xp);
- fFS.codeAppend("}");
-}
-
void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
}
-void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
- // TODO: Once will readDst is only xp enable this assert and remove it from the
- // FragmentProcessor verify()
- //SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
-}
-
void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
+ fGeometryProcessor, fFragmentProcessors.get()));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "../GrGLProgramDataManager.h"
#include "../GrGLUniformHandle.h"
#include "../GrGLGeometryProcessor.h"
-#include "../GrGLXferProcessor.h"
#include "../../GrOptDrawState.h"
#include "../../GrPendingFragmentStage.h"
friend class GrGLVertexBuilder;
friend class GrGLGeometryBuilder;
- friend class GrGLXferBuilder;
friend class GrGLFragmentShaderBuilder;
};
*/
};
-/* a specializations for XPs. Lets the user add uniforms and FS code */
-class GrGLXPBuilder : public virtual GrGLUniformBuilder {
-public:
- virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
-
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
struct GrGLInstalledProc;
struct GrGLInstalledGeoProc;
-struct GrGLInstalledXferProc;
struct GrGLInstalledFragProc;
struct GrGLInstalledFragProcs;
* respective builders
*/
class GrGLProgramBuilder : public GrGLGPBuilder,
- public GrGLFPBuilder,
- public GrGLXPBuilder {
+ public GrGLFPBuilder {
public:
/** Generates a shader program.
*
void emitAndInstallProc(const GrGeometryProcessor&,
const char* outColor,
const char* outCoverage);
- void emitAndInstallXferProc(const GrXferProcessor&,
- const GrGLSLExpr4& colorIn,
- const GrGLSLExpr4& coverageIn);
void verify(const GrGeometryProcessor&);
- void verify(const GrXferProcessor&);
void verify(const GrFragmentProcessor&);
void emitSamplers(const GrProcessor&,
GrGLProcessor::TextureSamplerArray* outSamplers,
int fStageIndex;
GrGLInstalledGeoProc* fGeometryProcessor;
- GrGLInstalledXferProc* fXferProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
const GrOptDrawState& fOptState;
SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
};
-struct GrGLInstalledXferProc : public GrGLInstalledProc {
- SkAutoTDelete<GrGLXferProcessor> fGLProc;
-};
-
struct GrGLInstalledFragProc : public GrGLInstalledProc {
GrGLInstalledFragProc() : fGLProc(NULL) {}
class ShaderVarHandle {
return SkRef(texture->asRenderTarget());
}
-static void set_random_xpf(GrContext* context, const GrDrawTargetCaps& caps, GrDrawState* ds,
- SkRandom* random, GrTexture* dummyTextures[]) {
- SkAutoTUnref<const GrXPFactory> xpf(
- GrProcessorTestFactory<GrXPFactory>::CreateStage(random, context, caps, dummyTextures));
- SkASSERT(xpf);
- ds->setXPFactory(xpf.get());
-}
-
static void set_random_gp(GrContext* context,
const GrDrawTargetCaps& caps,
GrDrawState* ds,
ds->enableState(state);
}
+// this function will randomly pick non-self referencing blend modes
+static void set_random_blend_func(GrDrawState* ds, SkRandom* random) {
+ GrBlendCoeff src;
+ do {
+ src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
+ } while (GrBlendCoeffRefsSrc(src));
+
+ GrBlendCoeff dst;
+ do {
+ dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff));
+ } while (GrBlendCoeffRefsDst(dst));
+
+ GrXPFactory* xpFactory = GrPorterDuffXPFactory::Create(src, dst);
+ ds->setXPFactory(xpFactory)->unref();
+}
+
// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
static void set_random_stencil(GrDrawState* ds, SkRandom* random) {
GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil,
usePathRendering,
&random,
dummyTextures);
-
- // creates a random xfer processor factory on the draw state
- set_random_xpf(fContext, gpu->glCaps(), &ds, &random, dummyTextures);
-
set_random_hints(&ds, &random);
set_random_state(&ds, &random);
+ set_random_blend_func(&ds, &random);
set_random_stencil(&ds, &random);
GrDeviceCoordTexture dstCopy;