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 "gl/GrGLXferProcessor.h"
9 
10 #include "GrXferProcessor.h"
11 #include "gl/builders/GrGLFragmentShaderBuilder.h"
12 #include "gl/builders/GrGLProgramBuilder.h"
13 
emitCode(const EmitArgs & args)14 void GrGLXferProcessor::emitCode(const EmitArgs& args) {
15     if (args.fXP.getDstCopyTexture()) {
16         bool topDown = kTopLeft_GrSurfaceOrigin == args.fXP.getDstCopyTexture()->origin();
17 
18         GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
19 
20         if (args.fXP.readsCoverage()) {
21             // We don't think any shaders actually output negative coverage, but just as a safety
22             // check for floating point precision errors we compare with <= here
23             fsBuilder->codeAppendf("if (all(lessThanEqual(%s, vec4(0)))) {"
24                                    "    discard;"
25                                    "}", args.fInputCoverage);
26         }
27 
28         const char* dstColor = fsBuilder->dstColor();
29 
30         const char* dstCopyTopLeftName;
31         const char* dstCopyCoordScaleName;
32 
33         fDstCopyTopLeftUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
34                                                    kVec2f_GrSLType,
35                                                    kDefault_GrSLPrecision,
36                                                    "DstCopyUpperLeft",
37                                                    &dstCopyTopLeftName);
38         fDstCopyScaleUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
39                                                 kVec2f_GrSLType,
40                                                 kDefault_GrSLPrecision,
41                                                 "DstCopyCoordScale",
42                                                 &dstCopyCoordScaleName);
43         const char* fragPos = fsBuilder->fragmentPosition();
44 
45         fsBuilder->codeAppend("// Read color from copy of the destination.\n");
46         fsBuilder->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
47                                fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
48 
49         if (!topDown) {
50             fsBuilder->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
51         }
52 
53         fsBuilder->codeAppendf("vec4 %s = ", dstColor);
54         fsBuilder->appendTextureLookup(args.fSamplers[0], "_dstTexCoord", kVec2f_GrSLType);
55         fsBuilder->codeAppend(";");
56     }
57 
58     this->onEmitCode(args);
59 }
60 
setData(const GrGLProgramDataManager & pdm,const GrXferProcessor & xp)61 void GrGLXferProcessor::setData(const GrGLProgramDataManager& pdm, const GrXferProcessor& xp) {
62     if (xp.getDstCopyTexture()) {
63         if (fDstCopyTopLeftUni.isValid()) {
64             pdm.set2f(fDstCopyTopLeftUni, static_cast<GrGLfloat>(xp.dstCopyTextureOffset().fX),
65                       static_cast<GrGLfloat>(xp.dstCopyTextureOffset().fY));
66             pdm.set2f(fDstCopyScaleUni, 1.f / xp.getDstCopyTexture()->width(),
67                       1.f / xp.getDstCopyTexture()->height());
68         } else {
69             SkASSERT(!fDstCopyScaleUni.isValid());
70         }
71     } else {
72         SkASSERT(!fDstCopyTopLeftUni.isValid());
73         SkASSERT(!fDstCopyScaleUni.isValid());
74     }
75     this->onSetData(pdm, xp);
76 }
77 
78