Create xfer processor backend.
This includes:
-Having an actual XP stage at the end of the gl pipeline.
-All Blending work is handled by XP until actually setting GL blend states
-GLPrograms test to test XP
BUG=skia:
Committed: https://skia.googlesource.com/skia/+/4dffc940c430eec66d4707490eace19c9b3f7904
Review URL: https://codereview.chromium.org/764643004
diff --git a/src/gpu/gl/GrGLProcessor.h b/src/gpu/gl/GrGLProcessor.h
index 6dccd33..a4fad75 100644
--- a/src/gpu/gl/GrGLProcessor.h
+++ b/src/gpu/gl/GrGLProcessor.h
@@ -117,14 +117,4 @@
typedef GrGLProcessor INHERITED;
};
-class GrGLXferProcessor : public GrGLFragmentProcessor {
-public:
- GrGLXferProcessor() {}
-
- virtual ~GrGLXferProcessor() {}
-
-private:
- typedef GrGLFragmentProcessor INHERITED;
-};
-
#endif
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 29c44ac..da687c1 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -12,11 +12,13 @@
#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)
@@ -57,6 +59,7 @@
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledGeoProc* geometryProcessor,
+ GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
: fColor(GrColor_ILLEGAL)
, fCoverage(0)
@@ -64,6 +67,7 @@
, fBuiltinUniformHandles(builtinUniforms)
, fProgramID(programID)
, fGeometryProcessor(geometryProcessor)
+ , fXferProcessor(xferProcessor)
, fFragmentProcessors(SkRef(fragmentProcessors))
, fDesc(desc)
, fGpu(gpu)
@@ -91,6 +95,9 @@
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);
@@ -162,6 +169,11 @@
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
@@ -284,8 +296,10 @@
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
+ GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, fragmentProcessors) {
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL,
+ xferProcessor, fragmentProcessors) {
}
void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(const GrOptDrawState& optState) {
@@ -303,9 +317,11 @@
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
+ GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
const SeparableVaryingInfoArray& separableVaryings)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fragmentProcessors) {
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms,
+ xferProcessor, fragmentProcessors) {
int count = separableVaryings.count();
fVaryings.push_back_n(count);
for (int i = 0; i < count; i++) {
@@ -353,9 +369,10 @@
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
+ GrGLInstalledXferProc* xp,
GrGLInstalledFragProcs* fps,
int texCoordSetCnt)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fps)
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, xp, fps)
, fTexCoordSetCnt(texCoordSetCnt) {
}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 36bf860..ea8be85 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -141,6 +141,7 @@
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledGeoProc* geometryProcessor,
+ GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
// Sets the texture units for samplers.
@@ -180,6 +181,7 @@
// the installed effects
SkAutoTDelete<GrGLInstalledGeoProc> fGeometryProcessor;
+ SkAutoTDelete<GrGLInstalledXferProc> fXferProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
GrProgramDesc fDesc;
@@ -205,6 +207,7 @@
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
+ GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
virtual void onSetMatrixAndRenderTargetHeight(const GrOptDrawState&);
@@ -223,6 +226,7 @@
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
+ GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
const SeparableVaryingInfoArray& separableVaryings);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
@@ -252,7 +256,8 @@
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledFragProcs* fragmentProcessors,
+ GrGLInstalledXferProc* xp,
+ GrGLInstalledFragProcs* fps,
int texCoordSetCnt);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
virtual void setTransformData(const GrPendingFragmentStage&,
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 068386c..2476c55 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -189,13 +189,21 @@
const GrFragmentProcessor& fp = *fps.getProcessor();
GrProcessorKeyBuilder b(&desc->fKey);
fp.getGLProcessorKey(gpu->glCaps(), &b);
- if (!get_meta_key(*fps.getProcessor(), gpu->glCaps(),
- gen_transform_key(fps, requiresLocalCoordAttrib), 0, &b)) {
+ if (!get_meta_key(fp, 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.
@@ -260,9 +268,6 @@
header->fFragPosKey = 0;
}
- header->fPrimaryOutputType = descInfo.fPrimaryOutputType;
- header->fSecondaryOutputType = descInfo.fSecondaryOutputType;
-
header->fColorEffectCnt = optState.numColorStages();
header->fCoverageEffectCnt = optState.numCoverageStages();
desc->finalize();
diff --git a/src/gpu/gl/GrGLXferProcessor.h b/src/gpu/gl/GrGLXferProcessor.h
new file mode 100644
index 0000000..5c92559
--- /dev/null
+++ b/src/gpu/gl/GrGLXferProcessor.h
@@ -0,0 +1,61 @@
+/*
+ * 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
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index c899eba..7db6abd 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1919,10 +1919,14 @@
}
}
-void GrGpuGL::flushBlend(const GrOptDrawState& optState, bool isLines,
- GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
+void GrGpuGL::flushBlend(const GrOptDrawState& optState) {
// Any optimization to disable blending should have already been applied and
// tweaked the coeffs to (1, 0).
+
+ GrXferProcessor::BlendInfo blendInfo;
+ optState.getXferProcessor()->getBlendInfo(&blendInfo);
+ GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
+ GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
bool blendOff = kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
if (blendOff) {
if (kNo_TriState != fHWBlendState.fEnabled) {
@@ -1941,7 +1945,7 @@
fHWBlendState.fSrcCoeff = srcCoeff;
fHWBlendState.fDstCoeff = dstCoeff;
}
- GrColor blendConst = optState.getBlendConstant();
+ GrColor blendConst = blendInfo.fBlendConstant;
if ((BlendCoeffReferencesConstant(srcCoeff) ||
BlendCoeffReferencesConstant(dstCoeff)) &&
(!fHWBlendState.fConstColorValid ||
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 8a60988..76995b9 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -172,11 +172,7 @@
size_t* indexOffsetInBytes);
// Subclasses should call this to flush the blend state.
- // The params should be the final coefficients to apply
- // (after any blending optimizations or dual source blending considerations
- // have been accounted for).
- void flushBlend(const GrOptDrawState& optState, bool isLines,
- GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff);
+ void flushBlend(const GrOptDrawState& optState);
bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ext); }
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index a808aa8..19ddc76 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -213,9 +213,6 @@
} else {
this->flushMiscFixedFunctionState(optState);
- GrBlendCoeff srcCoeff = optState.getSrcBlendCoeff();
- GrBlendCoeff dstCoeff = optState.getDstBlendCoeff();
-
fCurrentProgram.reset(fProgramCache->getProgram(optState));
if (NULL == fCurrentProgram.get()) {
SkDEBUGFAIL("Failed to create program!");
@@ -230,7 +227,7 @@
fHWProgramID = programID;
}
- this->flushBlend(optState, kDrawLines_DrawType == optState.drawType(), srcCoeff, dstCoeff);
+ this->flushBlend(optState);
fCurrentProgram->setData(optState);
}
diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
index 49be12d..b6daca7 100644
--- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp
@@ -256,55 +256,6 @@
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();
diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
index 03f0e7f..456ec4f 100644
--- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
+++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h
@@ -100,8 +100,6 @@
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);
diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
index b251593..b90bab2 100644
--- a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
@@ -45,5 +45,6 @@
GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fFragmentProcessors.get(), fTexCoordSetCnt));
+ fXferProcessor, fFragmentProcessors.get(),
+ fTexCoordSetCnt));
}
diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
index f5a5586..ba19275 100644
--- a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
@@ -72,5 +72,6 @@
// building
this->resolveSeparableVaryings(programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fFragmentProcessors.get(), fSeparableVaryingInfos));
+ fXferProcessor, fFragmentProcessors.get(),
+ fSeparableVaryingInfos));
}
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 7929801..daa0b6b 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -9,6 +9,7 @@
#include "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h"
+#include "../GrGLXferProcessor.h"
#include "../GrGpuGL.h"
#include "GrCoordTransform.h"
#include "GrGLLegacyNvprProgramBuilder.h"
@@ -55,20 +56,12 @@
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());
@@ -95,6 +88,7 @@
, fOutOfStage(true)
, fStageIndex(-1)
, fGeometryProcessor(NULL)
+ , fXferProcessor(NULL)
, fOptState(optState)
, fDesc(optState.programDesc())
, fGpu(gpu)
@@ -260,6 +254,8 @@
if (fOptState.hasGeometryProcessor()) {
fVS.transformToNormalizedDeviceSpace();
}
+
+ this->emitAndInstallXferProc(*fOptState.getXferProcessor(), *inputColor, *inputCoverage);
}
void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
@@ -368,10 +364,55 @@
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());
@@ -543,7 +584,7 @@
GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fGeometryProcessor, fFragmentProcessors.get()));
+ fGeometryProcessor, fXferProcessor, fFragmentProcessors.get()));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index 1798e60..69eed27 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -14,6 +14,7 @@
#include "../GrGLProgramDataManager.h"
#include "../GrGLUniformHandle.h"
#include "../GrGLGeometryProcessor.h"
+#include "../GrGLXferProcessor.h"
#include "../../GrOptDrawState.h"
#include "../../GrPendingFragmentStage.h"
@@ -111,6 +112,7 @@
friend class GrGLVertexBuilder;
friend class GrGLGeometryBuilder;
+ friend class GrGLXferBuilder;
friend class GrGLFragmentShaderBuilder;
};
@@ -170,8 +172,18 @@
*/
};
+/* 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;
@@ -183,7 +195,8 @@
* respective builders
*/
class GrGLProgramBuilder : public GrGLGPBuilder,
- public GrGLFPBuilder {
+ public GrGLFPBuilder,
+ public GrGLXPBuilder {
public:
/** Generates a shader program.
*
@@ -283,8 +296,12 @@
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,
@@ -358,6 +375,7 @@
int fStageIndex;
GrGLInstalledGeoProc* fGeometryProcessor;
+ GrGLInstalledXferProc* fXferProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
const GrOptDrawState& fOptState;
@@ -391,6 +409,10 @@
SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
};
+struct GrGLInstalledXferProc : public GrGLInstalledProc {
+ SkAutoTDelete<GrGLXferProcessor> fGLProc;
+};
+
struct GrGLInstalledFragProc : public GrGLInstalledProc {
GrGLInstalledFragProc() : fGLProc(NULL) {}
class ShaderVarHandle {