diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-17 13:36:14 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-17 13:36:14 +0000 |
commit | 67e78c9e47c38a51816412a24a10f4fe2db142a3 (patch) | |
tree | 13190c7dcbb06a727a0ace698609ca39d15c158f | |
parent | 1947ba6b9efc155ebca302696a05c736c0ad7808 (diff) |
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
-rw-r--r-- | include/core/SkColorFilter.h | 7 | ||||
-rw-r--r-- | include/effects/SkColorMatrix.h | 6 | ||||
-rw-r--r-- | include/effects/SkColorMatrixFilter.h | 3 | ||||
-rw-r--r-- | include/gpu/GrCustomStageUnitTest.h | 2 | ||||
-rw-r--r-- | include/gpu/GrPaint.h | 30 | ||||
-rw-r--r-- | src/core/SkColorFilter.cpp | 4 | ||||
-rw-r--r-- | src/effects/SkColorMatrixFilter.cpp | 112 | ||||
-rw-r--r-- | src/gpu/GrDrawState.cpp | 6 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 35 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 43 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 28 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 53 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 8 |
16 files changed, 197 insertions, 165 deletions
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h index 935b691160..44d3f8521a 100644 --- a/include/core/SkColorFilter.h +++ b/include/core/SkColorFilter.h @@ -15,6 +15,8 @@ #include "SkXfermode.h" class SkBitmap; +class GrCustomStage; +class GrContext; class SK_API SkColorFilter : public SkFlattenable { public: @@ -113,6 +115,11 @@ public: */ static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add); + /** A subclass may implement this factory function to work with the GPU backend. If the return + is non-NULL then the caller owns a ref on the returned object. + */ + virtual GrCustomStage* asNewCustomStage(GrContext*) const; + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() protected: SkColorFilter() {} diff --git a/include/effects/SkColorMatrix.h b/include/effects/SkColorMatrix.h index ff02d9ddc7..84a3b7c497 100644 --- a/include/effects/SkColorMatrix.h +++ b/include/effects/SkColorMatrix.h @@ -39,6 +39,12 @@ public: void setSaturation(SkScalar sat); void setRGB2YUV(); void setYUV2RGB(); + + bool operator==(const SkColorMatrix& other) const { + return 0 == memcmp(fMat, other.fMat, sizeof(fMat)); + } + + bool operator!=(const SkColorMatrix& other) const { return !((*this) == other); } }; #endif diff --git a/include/effects/SkColorMatrixFilter.h b/include/effects/SkColorMatrixFilter.h index 005781f084..08eef5de88 100644 --- a/include/effects/SkColorMatrixFilter.h +++ b/include/effects/SkColorMatrixFilter.h @@ -21,6 +21,9 @@ public: virtual void filterSpan16(const uint16_t src[], int count, uint16_t[]) SK_OVERRIDE; virtual uint32_t getFlags() SK_OVERRIDE; virtual bool asColorMatrix(SkScalar matrix[20]) SK_OVERRIDE; +#if SK_SUPPORT_GPU + virtual GrCustomStage* asNewCustomStage(GrContext*) const SK_OVERRIDE; +#endif struct State { int32_t fArray[20]; diff --git a/include/gpu/GrCustomStageUnitTest.h b/include/gpu/GrCustomStageUnitTest.h index e0f179db63..0e12f2d229 100644 --- a/include/gpu/GrCustomStageUnitTest.h +++ b/include/gpu/GrCustomStageUnitTest.h @@ -58,7 +58,7 @@ private: /** GrCustomStage subclasses should insert this macro in their implemenation file. They must then * also implement this static function: - * GrCustomStage* CreateStage(SkRandom*, GrContext*, GrTexture* dummyTextures[2]); + * GrCustomStage* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2]); * dummyTextures[] are valied textures that they can optionally use for their texture accesses. The * first texture has config kSkia8888_PM_GrPixelConfig and the second has kAlpha_8_GrPixelConfig. * TestCreate functions are also free to create additional textures using the GrContext. diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h index 843a9348e5..06c16af578 100644 --- a/include/gpu/GrPaint.h +++ b/include/gpu/GrPaint.h @@ -25,8 +25,7 @@ * The primitive color computation starts with the color specified by setColor(). This color is the * input to the first color stage. Each color stage feeds its output to the next color stage. The * final color stage's output color is input to the color filter specified by - * setXfermodeColorFilter which it turn feeds into the color matrix. The output of the color matrix - * is the final source color, S. + * setXfermodeColorFilter which produces the final source color, S. * * Fractional pixel coverage follows a similar flow. The coverage is initially the value specified * by setCoverage(). This is input to the first coverage stage. Coverage stages are chained @@ -40,7 +39,7 @@ * Note that the coverage is applied after the blend. This is why they are computed as distinct * values. * - * TODO: Encapsulate setXfermodeColorFilter and color matrix in stages and remove from GrPaint. + * TODO: Encapsulate setXfermodeColorFilter in a GrCustomStage and remove from GrPaint. */ class GrPaint { public: @@ -104,28 +103,11 @@ public: GrColor getColorFilterColor() const { return fColorFilterColor; } /** - * Turns off application of a color matrix. By default the color matrix is disabled. - */ - void disableColorMatrix() { fColorMatrixEnabled = false; } - - /** - * Specifies and enables a 4 x 5 color matrix. - */ - void setColorMatrix(const float matrix[20]) { - fColorMatrixEnabled = true; - memcpy(fColorMatrix, matrix, sizeof(fColorMatrix)); - } - - bool isColorMatrixEnabled() const { return fColorMatrixEnabled; } - const float* getColorMatrix() const { return fColorMatrix; } - - /** - * Disables both the matrix and SkXfermode::Mode color filters. + * Disables the SkXfermode::Mode color filter. */ void resetColorFilter() { fColorFilterXfermode = SkXfermode::kDst_Mode; fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); - fColorMatrixEnabled = false; } /** @@ -246,10 +228,6 @@ public: fColorFilterColor = paint.fColorFilterColor; fColorFilterXfermode = paint.fColorFilterXfermode; - fColorMatrixEnabled = paint.fColorMatrixEnabled; - if (fColorMatrixEnabled) { - memcpy(fColorMatrix, paint.fColorMatrix, sizeof(fColorMatrix)); - } for (int i = 0; i < kMaxColorStages; ++i) { if (paint.isColorStageEnabled(i)) { @@ -295,14 +273,12 @@ private: GrBlendCoeff fDstBlendCoeff; bool fAntiAlias; bool fDither; - bool fColorMatrixEnabled; GrColor fColor; uint8_t fCoverage; GrColor fColorFilterColor; SkXfermode::Mode fColorFilterXfermode; - float fColorMatrix[20]; void resetBlend() { fSrcBlendCoeff = kOne_GrBlendCoeff; diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp index fee34ed805..3651d7e618 100644 --- a/src/core/SkColorFilter.cpp +++ b/src/core/SkColorFilter.cpp @@ -40,6 +40,10 @@ SkColor SkColorFilter::filterColor(SkColor c) { return SkUnPreMultiply::PMColorToColor(dst); } +GrCustomStage* SkColorFilter::asNewCustomStage(GrContext*) const { + return NULL; +} + /////////////////////////////////////////////////////////////////////////////// SkFilterShader::SkFilterShader(SkShader* shader, SkColorFilter* filter) { diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp index 2102e9b81e..f3bc2a7f2e 100644 --- a/src/effects/SkColorMatrixFilter.cpp +++ b/src/effects/SkColorMatrixFilter.cpp @@ -317,3 +317,115 @@ bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) { } return true; } + +#if SK_SUPPORT_GPU +#include "GrCustomStage.h" +#include "gl/GrGLProgramStage.h" + +class ColorMatrixEffect : public GrCustomStage { +public: + static const char* Name() { return "Color Matrix"; } + + ColorMatrixEffect(const SkColorMatrix& matrix) : GrCustomStage(0), fMatrix(matrix) {} + + virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE { + return GrTProgramStageFactory<ColorMatrixEffect>::getInstance(); + } + + virtual bool isEqual(const GrCustomStage& s) const { + const ColorMatrixEffect& cme = static_cast<const ColorMatrixEffect&>(s); + return cme.fMatrix == fMatrix; + } + + GR_DECLARE_CUSTOM_STAGE_TEST; + + class GLProgramStage : public GrGLProgramStage { + public: + // this class always generates the same code. + static StageKey GenKey(const GrCustomStage& s, const GrGLCaps&) { return 0; } + + GLProgramStage(const GrProgramStageFactory& factory, + const GrCustomStage& stage) + : GrGLProgramStage(factory) + , fMatrixHandle(GrGLUniformManager::kInvalidUniformHandle) + , fVectorHandle(GrGLUniformManager::kInvalidUniformHandle) { + } + + virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE { + fMatrixHandle = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, + kMat44f_GrSLType, + "ColorMatrix"); + fVectorHandle = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, + kVec4f_GrSLType, + "ColorMatrixVector"); + } + + virtual void emitVS(GrGLShaderBuilder* builder, const char* vertexCoords) SK_OVERRIDE { + } + + virtual void emitFS(GrGLShaderBuilder* builder, + const char* outputColor, + const char* inputColor, + const TextureSamplerArray&) SK_OVERRIDE { + if (NULL == inputColor) { + // could optimize this case, but we aren't for now. + inputColor = GrGLSLOnesVecf(4); + } + // The max() is to guard against 0 / 0 during unpremul when the incoming color is + // transparent black. + builder->fFSCode.appendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor); + builder->fFSCode.appendf("\t%s = %s * vec4(%s.rgb / nonZeroAlpha, nonZeroAlpha) + %s;\n", + outputColor, + builder->getUniformCStr(fMatrixHandle), + inputColor, + builder->getUniformCStr(fVectorHandle)); + builder->fFSCode.appendf("\t%s.rgb *= %s.a;\n", outputColor, outputColor); + } + + virtual void setData(const GrGLUniformManager& uniManager, + const GrCustomStage& stage, + const GrRenderTarget*, + int /* stageNum */) SK_OVERRIDE { + const ColorMatrixEffect& cme = static_cast<const ColorMatrixEffect&>(stage); + const float* m = cme.fMatrix.fMat; + // The GL matrix is transposed from SkColorMatrix. + 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 const float kScale = 1.0f / 255.0f; + GrGLfloat vec[] = { + m[4] * kScale, m[9] * kScale, m[14] * kScale, m[19] * kScale, + }; + uniManager.setMatrix4fv(fMatrixHandle, 0, 1, mt); + uniManager.set4fv(fVectorHandle, 0, 1, vec); + } + + private: + GrGLUniformManager::UniformHandle fMatrixHandle; + GrGLUniformManager::UniformHandle fVectorHandle; + }; + +private: + SkColorMatrix fMatrix; +}; + +GR_DEFINE_CUSTOM_STAGE_TEST(ColorMatrixEffect); + +GrCustomStage* ColorMatrixEffect::TestCreate(SkRandom* random, + GrContext*, + GrTexture* dummyTextures[2]) { + SkColorMatrix colorMatrix; + for (int i = 0; i < SK_ARRAY_COUNT(colorMatrix.fMat); ++i) { + colorMatrix.fMat[i] = random->nextSScalar1(); + } + return SkNEW_ARGS(ColorMatrixEffect, (colorMatrix)); +} + +GrCustomStage* SkColorMatrixFilter::asNewCustomStage(GrContext*) const { + return SkNEW_ARGS(ColorMatrixEffect, (fMatrix)); +} + +#endif diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index c95049a491..0f0a27a928 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -36,12 +36,6 @@ void GrDrawState::setFromPaint(const GrPaint& paint) { 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 7bfb5e5beb..e3121eadb5 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -651,22 +651,6 @@ public: /// @} /////////////////////////////////////////////////////////////////////////// - /// @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 @@ public: * 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 @@ public: 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 @@ public: } } - if (kColorMatrix_StateBit & s.fFlagBits) { - memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix)); - } - return *this; } @@ -942,8 +909,6 @@ private: // 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 02bfdbd215..7ea1e756f5 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -500,28 +500,37 @@ inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev, 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 2703110df6..3c3d852511 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -511,7 +511,6 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) { #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 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) { 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 GrGLProgram::genProgram(const GrCustomStage** customStages) { } 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 @@ bool GrGLProgram::genProgram(const GrCustomStage** customStages) { 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 e51f66351c..cdb2c4b6a2 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -155,7 +155,6 @@ public: 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 @@ private: 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 157d9bc2ec..4df7a983f3 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -2020,10 +2020,12 @@ void GrGpuGL::flushBoundTextureAndParams(int stage) { 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 351ff53feb..0a0c52bb5a 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -229,14 +229,6 @@ private: // 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 @@ private: 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 e579331614..5f5a3a6f95 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -200,6 +200,9 @@ void GrGpuGL::flushTextureMatrix(int s) { // 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::flushTextureMatrix(int s) { } } -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 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { } } } - this->flushColorMatrix(); } this->flushStencil(type); this->flushViewMatrix(type); @@ -645,8 +627,6 @@ void GrGpuGL::buildProgram(bool isPoints, 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 @@ void GrGpuGL::buildProgram(bool isPoints, 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 @@ void GrGpuGL::buildProgram(bool isPoints, 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 diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index deaf0342ba..16fd5650c8 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -114,8 +114,6 @@ bool GrGpuGL::programUnitTest() { } else { } - pdesc.fColorMatrixEnabled = random_bool(&random); - if (this->getCaps().dualSourceBlendingSupport()) { pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); } else { @@ -174,17 +172,17 @@ static void GLProgramsTest(skiatest::Reporter* reporter, GrContext* context) { REPORTER_ASSERT(reporter, shadersGpu->programUnitTest()); } - #include "TestClassDef.h" DEFINE_GPUTESTCLASS("GLPrograms", GLProgramsTestClass, GLProgramsTest) // This is evil evil evil. The linker may throw away whole translation units as dead code if it -// thinks none of the functions are called. It will do this even if there are static initilializers +// thinks none of the functions are called. It will do this even if there are static initializers // in the unit that could pass pointers to functions from the unit out to other translation units! // We force some of the effects that would otherwise be discarded to link here. #include "SkLightingImageFilter.h" #include "SkMagnifierImageFilter.h" +#include "SkColorMatrixFilter.h" void forceLinking(); @@ -192,6 +190,8 @@ void forceLinking() { SkLightingImageFilter::CreateDistantLitDiffuse(SkPoint3(0,0,0), 0, 0, 0); SkMagnifierImageFilter mag(SkRect::MakeWH(SK_Scalar1, SK_Scalar1), SK_Scalar1); GrConfigConversionEffect::Create(NULL, false); + SkScalar matrix[20]; + SkColorMatrixFilter cmf(matrix); } #endif |