diff options
author | Scroggo <Scroggo@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-05-11 14:05:25 +0000 |
---|---|---|
committer | Scroggo <Scroggo@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-05-11 14:05:25 +0000 |
commit | 97c88c255cff3dbb8343c5d090526fdbedad6dd6 (patch) | |
tree | 018288372381d57dfd8eef285be5d7354067e926 /gpu/src | |
parent | 0faac1e8579088a39f38d02ff675f14d7deb608d (diff) |
Add color filters to gpu path.
git-svn-id: http://skia.googlecode.com/svn/trunk@1297 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu/src')
-rw-r--r-- | gpu/src/GrContext.cpp | 1 | ||||
-rw-r--r-- | gpu/src/GrDrawTarget.cpp | 5 | ||||
-rw-r--r-- | gpu/src/GrGLProgram.cpp | 116 | ||||
-rw-r--r-- | gpu/src/GrGLProgram.h | 8 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders.cpp | 15 |
5 files changed, 131 insertions, 14 deletions
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index 2d93e4bbd6..8cb932b2c4 100644 --- a/gpu/src/GrContext.cpp +++ b/gpu/src/GrContext.cpp @@ -1335,6 +1335,7 @@ void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) { target->disableState(GrDrawTarget::kAntialias_StateBit); } target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); + target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); } GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint, diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp index 3810043f5e..695a2abdbb 100644 --- a/gpu/src/GrDrawTarget.cpp +++ b/gpu/src/GrDrawTarget.cpp @@ -380,6 +380,11 @@ void GrDrawTarget::setColor(GrColor c) { fCurrDrawState.fColor = c; } +void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) { + fCurrDrawState.fColorFilterColor = c; + fCurrDrawState.fColorFilterXfermode = mode; +} + void GrDrawTarget::setAlpha(uint8_t a) { this->setColor((a << 24) | (a << 16) | (a << 8) | a); } diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp index abed043735..f89de9b5da 100644 --- a/gpu/src/GrGLProgram.cpp +++ b/gpu/src/GrGLProgram.cpp @@ -21,6 +21,8 @@ #include "GrGLEffect.h" #include "GrMemory.h" +#include "SkXfermode.h" + namespace { const char* GrPrecision() { @@ -52,6 +54,7 @@ const char* GrShaderPrecision() { #define POS_ATTR_NAME "aPosition" #define COL_ATTR_NAME "aColor" #define COL_UNI_NAME "uColor" +#define COL_FILTER_UNI_NAME "uColorFilter" static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) { *s = "aTexCoord"; @@ -174,6 +177,57 @@ void GrGLProgram::doGLPost() const { } } +/** + * Create a text coefficient to be used in fragment shader code. + */ +static void coefficientString(GrStringBuilder& str, SkXfermode::Coeff coeff, + const char* src, const char* dst) { + switch (coeff) { + case SkXfermode::kZero_Coeff: /** 0 */ + str = "0.0"; + break; + case SkXfermode::kOne_Coeff: /** 1 */ + str = "1.0"; + break; + case SkXfermode::kSA_Coeff: /** src alpha */ + str.appendf("%s.a", src); + break; + case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ + str.appendf("(1.0 - %s.a)", src); + break; + case SkXfermode::kDA_Coeff: /** dst alpha */ + str.appendf("%s.a", dst); + break; + case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ + str.appendf("(1.0 - %s.a)", dst); + break; + case SkXfermode::kSC_Coeff: + str.append(src); + break; + default: + break; + } +} + +/** + * Adds a line to the fragment shader code which modifies the color by + * the specified color filter. + */ +static void addColorFilter(GrStringBuilder& FSCode, const char * outputVar, + SkXfermode::Mode colorFilterXfermode, const char* dstColor) { + SkXfermode::Coeff srcCoeff, dstCoeff; + bool success = SkXfermode::ModeAsCoeff(colorFilterXfermode, + &srcCoeff, &dstCoeff); + // We currently do not handle modes that cannot be represented as + // coefficients. + GrAssert(success); + GrStringBuilder srcCoeffStr, dstCoeffStr; + coefficientString(srcCoeffStr, srcCoeff, COL_FILTER_UNI_NAME, dstColor); + coefficientString(dstCoeffStr, dstCoeff, COL_FILTER_UNI_NAME, dstColor); + FSCode.appendf("\t%s = %s*%s + %s*%s;\n", outputVar, srcCoeffStr.c_str(), + COL_FILTER_UNI_NAME, dstCoeffStr.c_str(), dstColor); +} + bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const { ShaderCodeSegments segments; @@ -230,23 +284,39 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const { } } + bool useColorFilter = + // The rest of transfer mode color filters have not been implemented + fProgramDesc.fColorFilterXfermode <= SkXfermode::kMultiply_Mode + // This mode has no effect. + && fProgramDesc.fColorFilterXfermode != SkXfermode::kDst_Mode; + bool onlyUseColorFilter = useColorFilter + && (fProgramDesc.fColorFilterXfermode == SkXfermode::kClear_Mode + || fProgramDesc.fColorFilterXfermode == SkXfermode::kSrc_Mode); + if (useColorFilter) { + // Set up a uniform for the color + segments.fFSUnis.append( "uniform vec4 " COL_FILTER_UNI_NAME ";\n"); + programData->fUniLocations.fColorFilterUni = kUseUniform; + } + // for each enabled stage figure out what the input coordinates are // and count the number of stages in use. const char* stageInCoords[GrDrawTarget::kNumStages]; int numActiveStages = 0; - for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { - if (fProgramDesc.fStages[s].fEnabled) { - if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) { - stageInCoords[s] = POS_ATTR_NAME; - } else { - int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); - // we better have input tex coordinates if stage is enabled. - GrAssert(tcIdx >= 0); - GrAssert(texCoordAttrs[tcIdx].size()); - stageInCoords[s] = texCoordAttrs[tcIdx].c_str(); + if (!onlyUseColorFilter) { + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + if (fProgramDesc.fStages[s].fEnabled) { + if (GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s) & layout) { + stageInCoords[s] = POS_ATTR_NAME; + } else { + int tcIdx = GrDrawTarget::VertexTexCoordsForStage(s, layout); + // we better have input tex coordinates if stage is enabled. + GrAssert(tcIdx >= 0); + GrAssert(texCoordAttrs[tcIdx].size()); + stageInCoords[s] = texCoordAttrs[tcIdx].c_str(); + } + ++numActiveStages; } - ++numActiveStages; } } @@ -254,10 +324,10 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const { // of each to the next and generating code for each stage. if (numActiveStages) { int currActiveStage = 0; + GrStringBuilder outColor; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if (fProgramDesc.fStages[s].fEnabled) { - GrStringBuilder outColor; - if (currActiveStage < (numActiveStages - 1)) { + if (currActiveStage < (numActiveStages - 1) || useColorFilter) { outColor = "color"; outColor.appendS32(currActiveStage); segments.fFSCode.appendf("\tvec4 %s;\n", outColor.c_str()); @@ -276,9 +346,21 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const { inColor = outColor; } } + if (useColorFilter) { + addColorFilter(segments.fFSCode, "gl_FragColor", + fProgramDesc.fColorFilterXfermode, outColor.c_str()); + } + } else { // we may not have any incoming color - segments.fFSCode.appendf("\tgl_FragColor = %s;\n", (inColor.size() ? inColor.c_str() : "vec4(1,1,1,1);\n")); + const char * incomingColor = (inColor.size() ? inColor.c_str() + : "vec4(1,1,1,1)"); + if (useColorFilter) { + addColorFilter(segments.fFSCode, "gl_FragColor", + fProgramDesc.fColorFilterXfermode, incomingColor); + } else { + segments.fFSCode.appendf("\tgl_FragColor = %s;\n", incomingColor); + } } segments.fVSCode.append("}\n"); segments.fFSCode.append("}\n"); @@ -495,6 +577,11 @@ void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const GR_GL(GetUniformLocation(progID, COL_UNI_NAME)); GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni); } + if (kUseUniform == programData->fUniLocations.fColorFilterUni) { + programData->fUniLocations.fColorFilterUni = + GR_GL(GetUniformLocation(progID, COL_FILTER_UNI_NAME)); + GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni); + } for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { StageUniLocations& locations = programData->fUniLocations.fStages[s]; @@ -550,6 +637,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const } programData->fViewMatrix = GrMatrix::InvalidMatrix(); programData->fColor = GrColor_ILLEGAL; + programData->fColorFilterColor = GrColor_ILLEGAL; } //============================================================================ diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h index 54818ec9d0..3b926a78c4 100644 --- a/gpu/src/GrGLProgram.h +++ b/gpu/src/GrGLProgram.h @@ -21,6 +21,8 @@ #include "GrStringBuilder.h" #include "GrDrawTarget.h" +#include "SkXfermode.h" + class GrBinHashKeyBuilder; class GrGLEffect; struct ShaderCodeSegments; @@ -107,6 +109,9 @@ private: bool fEmitsPointSize; + GrColor fColorFilterColor; + SkXfermode::Mode fColorFilterXfermode; + struct StageDesc { enum OptFlagBits { kNoPerspective_OptFlagBit = 0x1, @@ -159,10 +164,12 @@ public: struct UniLocations { GrGLint fViewMatrixUni; GrGLint fColorUni; + GrGLint fColorFilterUni; StageUniLocations fStages[GrDrawTarget::kNumStages]; void reset() { fViewMatrixUni = kUnusedUniform; fColorUni = kUnusedUniform; + fColorFilterUni = kUnusedUniform; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { fStages[s].reset(); } @@ -217,6 +224,7 @@ public: // these reflect the current values of uniforms // (GL uniform values travel with program) GrColor fColor; + GrColor fColorFilterColor; GrMatrix fTextureMatrices[GrDrawTarget::kNumStages]; // width and height used for normalized texel size int fTextureWidth[GrDrawTarget::kNumStages]; diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp index 3ce6e55d69..2487563122 100644 --- a/gpu/src/GrGpuGLShaders.cpp +++ b/gpu/src/GrGpuGLShaders.cpp @@ -438,6 +438,19 @@ void GrGpuGLShaders::flushColor() { GrCrash("Unknown color type."); } } + if (fProgramData->fUniLocations.fColorFilterUni + != GrGLProgram::kUnusedUniform + && fProgramData->fColorFilterColor + != fCurrDrawState.fColorFilterColor) { + float c[] = { + GrColorUnpackR(fCurrDrawState.fColorFilterColor) / 255.f, + GrColorUnpackG(fCurrDrawState.fColorFilterColor) / 255.f, + GrColorUnpackB(fCurrDrawState.fColorFilterColor) / 255.f, + GrColorUnpackA(fCurrDrawState.fColorFilterColor) / 255.f + }; + GR_GL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); + fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor; + } } @@ -693,6 +706,8 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) { fCurrentProgram.fStageEffects[s] = NULL; } } + desc.fColorFilterColor = fCurrDrawState.fColorFilterColor; + desc.fColorFilterXfermode = fCurrDrawState.fColorFilterXfermode; } |