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