| Index: src/gpu/gl/GrGLShaderBuilder.cpp | 
| =================================================================== | 
| --- src/gpu/gl/GrGLShaderBuilder.cpp	(revision 8448) | 
| +++ src/gpu/gl/GrGLShaderBuilder.cpp	(working copy) | 
| @@ -35,15 +35,26 @@ | 
| } | 
|  | 
| /** | 
| - * Do we need to either map r,g,b->a or a->r. | 
| + * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are | 
| + * present in the texture's config. swizzleComponentMask indicates the channels present in the | 
| + * shader swizzle. | 
| */ | 
| inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, | 
| -                                             const GrTextureAccess& access) { | 
| -    if (GrPixelConfigIsAlphaOnly(access.getTexture()->config())) { | 
| -        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & access.swizzleMask())) { | 
| +                                             uint32_t configComponentMask, | 
| +                                             uint32_t swizzleComponentMask) { | 
| +    if (caps.textureSwizzleSupport()) { | 
| +        // Any remapping is handled using texture swizzling not shader modifications. | 
| +        return false; | 
| +    } | 
| +    // check if the texture is alpha-only | 
| +    if (kA_GrColorComponentFlag == configComponentMask) { | 
| +        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) { | 
| +            // we must map the swizzle 'a's to 'r'. | 
| return true; | 
| } | 
| -        if (kRGB_GrColorComponentFlags & access.swizzleMask()) { | 
| +        if (kRGB_GrColorComponentFlags & swizzleComponentMask) { | 
| +            // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that | 
| +            // alpha-only textures smear alpha across all four channels when read. | 
| return true; | 
| } | 
| } | 
| @@ -76,16 +87,13 @@ | 
|  | 
| } | 
|  | 
| +static const char kDstColorName[] = "_dstColor"; | 
| + | 
| /////////////////////////////////////////////////////////////////////////////// | 
|  | 
| -// Architectural assumption: always 2-d input coords. | 
| -// Likely to become non-constant and non-static, perhaps even | 
| -// varying by stage, if we use 1D textures for gradients! | 
| -//const int GrGLShaderBuilder::fCoordDims = 2; | 
| - | 
| GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, | 
| GrGLUniformManager& uniformManager, | 
| -                                     bool explicitLocalCoords) | 
| +                                     const GrGLProgramDesc& desc) | 
| : fUniforms(kVarsPerBlock) | 
| , fVSAttrs(kVarsPerBlock) | 
| , fVSOutputs(kVarsPerBlock) | 
| @@ -93,16 +101,22 @@ | 
| , fGSOutputs(kVarsPerBlock) | 
| , fFSInputs(kVarsPerBlock) | 
| , fFSOutputs(kMaxFSOutputs) | 
| -    , fUsesGS(false) | 
| , fCtxInfo(ctxInfo) | 
| , fUniformManager(uniformManager) | 
| , fCurrentStageIdx(kNonStageIdx) | 
| +#if GR_GL_EXPERIMENTAL_GS | 
| +    , fUsesGS(desc.fExperimentalGS) | 
| +#else | 
| +    , fUsesGS(false) | 
| +#endif | 
| , fSetupFragPosition(false) | 
| -    , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) { | 
| +    , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) | 
| +    , fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle) | 
| +    , fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle) { | 
|  | 
| fPositionVar = &fVSAttrs.push_back(); | 
| fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); | 
| -    if (explicitLocalCoords) { | 
| +    if (desc.fAttribBindings & GrDrawState::kLocalCoords_AttribBindingsBit) { | 
| fLocalCoordsVar = &fVSAttrs.push_back(); | 
| fLocalCoordsVar->set(kVec2f_GrSLType, | 
| GrGLShaderVar::kAttribute_TypeModifier, | 
| @@ -110,8 +124,47 @@ | 
| } else { | 
| fLocalCoordsVar = fPositionVar; | 
| } | 
| +    if (kNoDstRead_DstReadKey != desc.fDstRead) { | 
| +        bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & desc.fDstRead); | 
| +        const char* dstCopyTopLeftName; | 
| +        const char* dstCopyCoordScaleName; | 
| +        uint32_t configMask; | 
| +        if (SkToBool(kUseAlphaConfig_DstReadKeyBit & desc.fDstRead)) { | 
| +            configMask = kA_GrColorComponentFlag; | 
| +        } else { | 
| +            configMask = kRGBA_GrColorComponentFlags; | 
| +        } | 
| +        fDstCopySampler.init(this, configMask, "rgba", 0); | 
| + | 
| +        fDstCopyTopLeftUniform = this->addUniform(kFragment_ShaderType, | 
| +                                                  kVec2f_GrSLType, | 
| +                                                  "DstCopyUpperLeft", | 
| +                                                  &dstCopyTopLeftName); | 
| +        fDstCopyScaleUniform     = this->addUniform(kFragment_ShaderType, | 
| +                                                    kVec2f_GrSLType, | 
| +                                                    "DstCopyCoordScale", | 
| +                                                    &dstCopyCoordScaleName); | 
| +        const char* fragPos = this->fragmentPosition(); | 
| +        this->fsCodeAppend("\t// Read color from copy of the destination.\n"); | 
| +        this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", | 
| +                            fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); | 
| +        if (!topDown) { | 
| +            this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); | 
| +        } | 
| +        this->fsCodeAppendf("\tvec4 %s = ", kDstColorName); | 
| +        this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord"); | 
| +        this->fsCodeAppend(";\n\n"); | 
| +    } | 
| } | 
|  | 
| +const char* GrGLShaderBuilder::dstColor() const { | 
| +    if (fDstCopySampler.isInitialized()) { | 
| +        return kDstColorName; | 
| +    } else { | 
| +        return NULL; | 
| +    } | 
| +} | 
| + | 
| void GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) { | 
| SkString* string = NULL; | 
| switch (type) { | 
| @@ -184,14 +237,26 @@ | 
| GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess( | 
| const GrTextureAccess& access, | 
| const GrGLCaps& caps) { | 
| -    GrBackendEffectFactory::EffectKey key = 0; | 
| +    uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); | 
| +    if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { | 
| +        return 1; | 
| +    } else { | 
| +        return 0; | 
| +    } | 
| +} | 
|  | 
| -    // Assume that swizzle support implies that we never have to modify a shader to adjust | 
| -    // for texture format/swizzle settings. | 
| -    if (!caps.textureSwizzleSupport() && swizzle_requires_alpha_remapping(caps, access)) { | 
| -        key = 1; | 
| +GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, | 
| +                                                               const GrGLCaps& caps) { | 
| +    uint32_t key = kYesDstRead_DstReadKeyBit; | 
| +    if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { | 
| +        // The fact that the config is alpha-only must be considered when generating code. | 
| +        key |= kUseAlphaConfig_DstReadKeyBit; | 
| } | 
| -    return key; | 
| +    if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { | 
| +        key |= kTopLeftOrigin_DstReadKeyBit; | 
| +    } | 
| +    GrAssert(static_cast<DstReadKey>(key) == key); | 
| +    return static_cast<DstReadKey>(key); | 
| } | 
|  | 
| const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { | 
|  |