1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "glsl/GrGLSLXferProcessor.h" 9 10 #include "GrXferProcessor.h" 11 #include "glsl/GrGLSLFragmentShaderBuilder.h" 12 #include "glsl/GrGLSLProgramDataManager.h" 13 #include "glsl/GrGLSLUniformHandler.h" 14 15 void GrGLSLXferProcessor::emitCode(const EmitArgs& args) { 16 if (!args.fXP.willReadDstColor()) { 17 this->emitOutputsForBlendState(args); 18 return; 19 } 20 21 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 22 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 23 const char* dstColor = fragBuilder->dstColor(); 24 25 if (args.fXP.getDstTexture()) { 26 bool topDown = kTopLeft_GrSurfaceOrigin == args.fXP.getDstTexture()->origin(); 27 28 if (args.fInputCoverage) { 29 // We don't think any shaders actually output negative coverage, but just as a safety 30 // check for floating point precision errors we compare with <= here 31 fragBuilder->codeAppendf("if (all(lessThanEqual(%s, vec4(0)))) {" 32 " discard;" 33 "}", args.fInputCoverage); 34 } 35 36 const char* dstTopLeftName; 37 const char* dstCoordScaleName; 38 39 fDstTopLeftUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 40 kVec2f_GrSLType, 41 kDefault_GrSLPrecision, 42 "DstTextureUpperLeft", 43 &dstTopLeftName); 44 fDstScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 45 kVec2f_GrSLType, 46 kDefault_GrSLPrecision, 47 "DstTextureCoordScale", 48 &dstCoordScaleName); 49 const char* fragPos = fragBuilder->fragmentPosition(); 50 51 fragBuilder->codeAppend("// Read color from copy of the destination.\n"); 52 fragBuilder->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", 53 fragPos, dstTopLeftName, dstCoordScaleName); 54 55 if (!topDown) { 56 fragBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); 57 } 58 59 fragBuilder->codeAppendf("vec4 %s = ", dstColor); 60 fragBuilder->appendTextureLookup(args.fSamplers[0], "_dstTexCoord", kVec2f_GrSLType); 61 fragBuilder->codeAppend(";"); 62 } 63 64 this->emitBlendCodeForDstRead(fragBuilder, 65 uniformHandler, 66 args.fInputColor, 67 args.fInputCoverage, 68 dstColor, 69 args.fOutputPrimary, 70 args.fOutputSecondary, 71 args.fXP); 72 } 73 74 void GrGLSLXferProcessor::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) { 75 if (xp.getDstTexture()) { 76 if (fDstTopLeftUni.isValid()) { 77 pdm.set2f(fDstTopLeftUni, static_cast<float>(xp.dstTextureOffset().fX), 78 static_cast<float>(xp.dstTextureOffset().fY)); 79 pdm.set2f(fDstScaleUni, 1.f / xp.getDstTexture()->width(), 80 1.f / xp.getDstTexture()->height()); 81 } else { 82 SkASSERT(!fDstScaleUni.isValid()); 83 } 84 } else { 85 SkASSERT(!fDstTopLeftUni.isValid()); 86 SkASSERT(!fDstScaleUni.isValid()); 87 } 88 this->onSetData(pdm, xp); 89 } 90 91 void GrGLSLXferProcessor::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder, 92 const char* srcCoverage, 93 const char* dstColor, 94 const char* outColor, 95 const char* outColorSecondary, 96 const GrXferProcessor& proc) { 97 if (proc.dstReadUsesMixedSamples()) { 98 if (srcCoverage) { 99 fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage); 100 fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage); 101 } else { 102 fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary); 103 } 104 } else if (srcCoverage) { 105 fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", 106 outColor, srcCoverage, outColor, srcCoverage, dstColor); 107 } 108 } 109