Use GrCustomStage to implement color matrix.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6716044
git-svn-id: http://skia.googlecode.com/svn/trunk@5975 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index c95049a..0f0a27a 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -36,12 +36,6 @@
this->setState(GrDrawState::kDither_StateBit, paint.isDither());
this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
- if (paint.isColorMatrixEnabled()) {
- this->enableState(GrDrawState::kColorMatrix_StateBit);
- this->setColorMatrix(paint.getColorMatrix());
- } else {
- this->disableState(GrDrawState::kColorMatrix_StateBit);
- }
this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
this->setColorFilter(paint.getColorFilterColor(), paint.getColorFilterMode());
this->setCoverage(paint.getCoverage());
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 7bfb5e5..e3121ea 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -651,22 +651,6 @@
/// @}
///////////////////////////////////////////////////////////////////////////
- /// @name Color Matrix
- ////
-
- /**
- * Sets the color matrix to use for the next draw.
- * @param matrix the 5x4 matrix to apply to the incoming color
- */
- void setColorMatrix(const float matrix[20]) {
- memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
- }
-
- const float* getColorMatrix() const { return fColorMatrix; }
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
// @name Edge AA
// Edge equations can be specified to perform anti-aliasing. Because the
// edges are specified as per-vertex data, vertices that are shared by
@@ -743,11 +727,6 @@
* operations.
*/
kNoColorWrites_StateBit = 0x08,
- /**
- * Draws will apply the color matrix, otherwise the color matrix is
- * ignored.
- */
- kColorMatrix_StateBit = 0x10,
// Users of the class may add additional bits to the vector
kDummyStateBit,
@@ -878,14 +857,6 @@
return false;
}
}
- if (kColorMatrix_StateBit & s.fFlagBits) {
- if (memcmp(fColorMatrix,
- s.fColorMatrix,
- sizeof(fColorMatrix))) {
- return false;
- }
- }
-
return true;
}
bool operator !=(const GrDrawState& s) const { return !(*this == s); }
@@ -914,10 +885,6 @@
}
}
- if (kColorMatrix_StateBit & s.fFlagBits) {
- memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
- }
-
return *this;
}
@@ -942,8 +909,6 @@
// This field must be last; it will not be copied or compared
// if the corresponding fTexture[] is NULL.
GrSamplerState fSamplerStates[kNumStages];
- // only compared if the color matrix enable flag is set
- float fColorMatrix[20]; // 5 x 4 matrix
typedef GrRefCnt INHERITED;
};
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 02bfdbd..7ea1e75 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -500,28 +500,37 @@
grPaint->setColor(SkColor2GrColor(skPaint.getColor()));
GrAssert(!grPaint->isColorStageEnabled(kShaderTextureIdx));
}
+
SkColorFilter* colorFilter = skPaint.getColorFilter();
- SkColor color;
- SkXfermode::Mode filterMode;
- SkScalar matrix[20];
- SkBitmap colorTransformTable;
- // TODO: SkColorFilter::asCustomStage()
- if (colorFilter != NULL && colorFilter->asColorMode(&color, &filterMode)) {
- if (!constantColor) {
- grPaint->setXfermodeColorFilter(filterMode, SkColor2GrColor(color));
- } else {
+ if (NULL != colorFilter) {
+ // if the source color is a constant then apply the filter here once rather than per pixel
+ // in a shader.
+ if (constantColor) {
SkColor filtered = colorFilter->filterColor(skPaint.getColor());
grPaint->setColor(SkColor2GrColor(filtered));
+ } else {
+ SkAutoTUnref<GrCustomStage> stage(colorFilter->asNewCustomStage(dev->context()));
+ if (NULL != stage.get()) {
+ grPaint->colorSampler(kColorFilterTextureIdx)->setCustomStage(stage);
+ } else {
+ // TODO: rewrite these using asNewCustomStage()
+ SkColor color;
+ SkXfermode::Mode filterMode;
+ SkBitmap colorTransformTable;
+ if (colorFilter->asColorMode(&color, &filterMode)) {
+ grPaint->setXfermodeColorFilter(filterMode, SkColor2GrColor(color));
+ } else if (colorFilter != NULL &&
+ colorFilter->asComponentTable(&colorTransformTable)) {
+ // pass NULL because the color table effect doesn't use tiling or filtering.
+ GrTexture* texture = act->set(dev, colorTransformTable, NULL);
+ GrSamplerState* colorSampler = grPaint->colorSampler(kColorFilterTextureIdx);
+ colorSampler->reset();
+ colorSampler->setCustomStage(SkNEW_ARGS(GrColorTableEffect, (texture)))->unref();
+ }
+ }
}
- } else if (colorFilter != NULL && colorFilter->asColorMatrix(matrix)) {
- grPaint->setColorMatrix(matrix);
- } else if (colorFilter != NULL && colorFilter->asComponentTable(&colorTransformTable)) {
- // pass NULL because the color table effect doesn't use tiling or filtering.
- GrTexture* texture = act->set(dev, colorTransformTable, NULL);
- GrSamplerState* colorSampler = grPaint->colorSampler(kColorFilterTextureIdx);
- colorSampler->reset();
- colorSampler->setCustomStage(SkNEW_ARGS(GrColorTableEffect, (texture)))->unref();
}
+
return true;
}
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 2703110..3c3d852 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -511,7 +511,6 @@
#endif
SkXfermode::Coeff colorCoeff, uniformCoeff;
- bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled);
// The rest of transfer mode color filters have not been implemented
if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
GR_DEBUGCODE(bool success =)
@@ -524,17 +523,15 @@
uniformCoeff = SkXfermode::kZero_Coeff;
}
- // no need to do the color filter / matrix at all if coverage is 0. The
- // output color is scaled by the coverage. All the dual source outputs are
- // scaled by the coverage as well.
+ // no need to do the color filter if coverage is 0. The output color is scaled by the coverage.
+ // All the dual source outputs are scaled by the coverage as well.
if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
colorCoeff = SkXfermode::kZero_Coeff;
uniformCoeff = SkXfermode::kZero_Coeff;
- applyColorMatrix = false;
}
// If we know the final color is going to be all zeros then we can
- // simplify the color filter coeffecients. needComputedColor will then
+ // simplify the color filter coefficients. needComputedColor will then
// come out false below.
if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
colorCoeff = SkXfermode::kZero_Coeff;
@@ -664,8 +661,7 @@
}
bool wroteFragColorZero = false;
if (SkXfermode::kZero_Coeff == uniformCoeff &&
- SkXfermode::kZero_Coeff == colorCoeff &&
- !applyColorMatrix) {
+ SkXfermode::kZero_Coeff == colorCoeff) {
builder.fFSCode.appendf("\t%s = %s;\n",
colorOutput.getName().c_str(),
GrGLSLZerosVecf(4));
@@ -677,22 +673,6 @@
colorCoeff, colorFilterColorUniName, color);
inColor = "filteredColor";
}
- if (applyColorMatrix) {
- const char* colMatrixName;
- const char* colMatrixVecName;
- fUniforms.fColorMatrixUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
- kMat44f_GrSLType, "ColorMatrix",
- &colMatrixName);
- fUniforms.fColorMatrixVecUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
- kVec4f_GrSLType, "ColorMatrixVec",
- &colMatrixVecName);
- const char* color = adjustInColor(inColor);
- builder.fFSCode.appendf("\tvec4 matrixedColor = %s * vec4(%s.rgb / %s.a, %s.a) + %s;\n",
- colMatrixName, color, color, color, colMatrixVecName);
- builder.fFSCode.append("\tmatrixedColor.rgb *= matrixedColor.a;\n");
-
- inColor = "matrixedColor";
- }
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage (coverage stages and edge aa)
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index e51f663..cdb2c4b 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -155,7 +155,6 @@
uint8_t fDualSrcOutput; // casts to enum DualSrcOutput
int8_t fFirstCoverageStage;
SkBool8 fEmitsPointSize;
- SkBool8 fColorMatrixEnabled;
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
};
@@ -224,16 +223,12 @@
UniformHandle fColorUni;
UniformHandle fCoverageUni;
UniformHandle fColorFilterUni;
- UniformHandle fColorMatrixUni;
- UniformHandle fColorMatrixVecUni;
StageUniforms fStages[GrDrawState::kNumStages];
Uniforms() {
fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
fColorUni = GrGLUniformManager::kInvalidUniformHandle;
fCoverageUni = GrGLUniformManager::kInvalidUniformHandle;
fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle;
- fColorMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
- fColorMatrixVecUni = GrGLUniformManager::kInvalidUniformHandle;
}
};
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 157d9bc..4df7a98 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -2020,10 +2020,12 @@
GrDrawState* drawState = this->drawState();
// FIXME: Assuming at most one texture per custom stage
const GrCustomStage* customStage = drawState->sampler(stage)->getCustomStage();
- GrGLTexture* nextTexture = static_cast<GrGLTexture*>(customStage->texture(0));
- if (NULL != nextTexture) {
- const GrTextureParams& texParams = customStage->textureAccess(0).getParams();
- this->flushBoundTextureAndParams(stage, texParams, nextTexture);
+ if (customStage->numTextures() > 0) {
+ GrGLTexture* nextTexture = static_cast<GrGLTexture*>(customStage->texture(0));
+ if (NULL != nextTexture) {
+ const GrTextureParams& texParams = customStage->textureAccess(0).getParams();
+ this->flushBoundTextureAndParams(stage, texParams, nextTexture);
+ }
}
}
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 351ff53..0a0c52b 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -229,14 +229,6 @@
// sets the MVP matrix uniform for currently bound program
void flushViewMatrix(DrawType type);
- // flushes the parameters to two point radial gradient
- void flushRadial2(int stage);
-
- // flushes the parameters for convolution
- void flushConvolution(int stage);
-
- // flushes the color matrix
- void flushColorMatrix();
// flushes dithering, color-mask, and face culling stat
void flushMiscFixedFunctionState();
@@ -251,7 +243,7 @@
const GrCustomStage** customStages,
ProgramDesc* desc);
- // Inits GrDrawTarget::Caps, sublcass may enable additional caps.
+ // Inits GrDrawTarget::Caps, subclass may enable additional caps.
void initCaps();
void initFSAASupport();
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index e579331..5f5a3a6 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -200,6 +200,9 @@
// FIXME: Still assuming only a single texture per custom stage
const GrCustomStage* stage = drawState.getSampler(s).getCustomStage();
+ if (0 == stage->numTextures()) {
+ return;
+ }
const GrGLTexture* texture = static_cast<const GrGLTexture*>(stage->texture(0));
if (NULL != texture) {
@@ -240,26 +243,6 @@
}
}
-void GrGpuGL::flushColorMatrix() {
- UniformHandle matrixUni = fCurrentProgram->fUniforms.fColorMatrixUni;
- UniformHandle vecUni = fCurrentProgram->fUniforms.fColorMatrixVecUni;
- if (kInvalidUniformHandle != matrixUni && kInvalidUniformHandle != vecUni) {
- const float* m = this->getDrawState().getColorMatrix();
- GrGLfloat mt[] = {
- m[0], m[5], m[10], m[15],
- m[1], m[6], m[11], m[16],
- m[2], m[7], m[12], m[17],
- m[3], m[8], m[13], m[18],
- };
- static float scale = 1.0f / 255.0f;
- GrGLfloat vec[] = {
- m[4] * scale, m[9] * scale, m[14] * scale, m[19] * scale,
- };
- fCurrentProgram->fUniformManager.setMatrix4f(matrixUni, mt);
- fCurrentProgram->fUniformManager.set4fv(vecUni, 0, 1, vec);
- }
-}
-
void GrGpuGL::flushColor(GrColor color) {
const ProgramDesc& desc = fCurrentProgram->getDesc();
const GrDrawState& drawState = this->getDrawState();
@@ -414,7 +397,6 @@
}
}
}
- this->flushColorMatrix();
}
this->flushStencil(type);
this->flushViewMatrix(type);
@@ -645,8 +627,6 @@
SkXfermode::kDst_Mode :
drawState.getColorFilterMode();
- desc->fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit);
-
// no reason to do edge aa or look at per-vertex coverage if coverage is
// ignored
if (skipCoverage) {
@@ -701,16 +681,23 @@
const GrSamplerState& sampler = drawState.getSampler(s);
// FIXME: Still assuming one texture per custom stage
const GrCustomStage* customStage = drawState.getSampler(s).getCustomStage();
- const GrGLTexture* texture = static_cast<const GrGLTexture*>(customStage->texture(0));
- GrMatrix samplerMatrix;
- sampler.getTotalMatrix(&samplerMatrix);
- if (NULL != texture) {
- // We call this helper function rather then simply checking the client-specified
- // texture matrix. This is because we may have to concat a y-inversion to account
- // for texture orientation.
- stage.fOptFlags |= TextureMatrixOptFlags(texture, sampler);
- }
+ if (customStage->numTextures() > 0) {
+ const GrGLTexture* texture =
+ static_cast<const GrGLTexture*>(customStage->texture(0));
+ GrMatrix samplerMatrix;
+ sampler.getTotalMatrix(&samplerMatrix);
+ if (NULL != texture) {
+ // We call this helper function rather then simply checking the client-specified
+ // texture matrix. This is because we may have to concat a y-inversion to account
+ // for texture orientation.
+ stage.fOptFlags |= TextureMatrixOptFlags(texture, sampler);
+ }
+ } else {
+ // Set identity to do the minimal amount of extra work for the no texture case.
+ // This will go away when custom stages manage their own texture matrix.
+ stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
+ }
setup_custom_stage(&stage, sampler, this->glCaps(), customStages,
fCurrentProgram.get(), s);
@@ -724,7 +711,7 @@
desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
- // other than pass through values fromthe VS to the FS anyway).
+ // other than pass through values from the VS to the FS anyway).
#if 0 && GR_GL_EXPERIMENTAL_GS
desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
#endif