OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGLSLFragmentShaderBuilder.h" | 8 #include "GrGLSLFragmentShaderBuilder.h" |
9 #include "GrRenderTarget.h" | 9 #include "GrRenderTarget.h" |
10 #include "gl/GrGLGpu.h" | 10 #include "gl/GrGLGpu.h" |
11 #include "glsl/GrGLSL.h" | 11 #include "glsl/GrGLSL.h" |
12 #include "glsl/GrGLSLCaps.h" | 12 #include "glsl/GrGLSLCaps.h" |
13 #include "glsl/GrGLSLProgramBuilder.h" | 13 #include "glsl/GrGLSLProgramBuilder.h" |
14 #include "glsl/GrGLSLUniformHandler.h" | 14 #include "glsl/GrGLSLUniformHandler.h" |
15 #include "glsl/GrGLSLVarying.h" | 15 #include "glsl/GrGLSLVarying.h" |
16 | 16 |
17 const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; | 17 const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; |
18 | 18 |
| 19 static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates
coords) { |
| 20 static const char* kArrayNames[] = { |
| 21 "deviceSpaceSampleOffsets", |
| 22 "windowSpaceSampleOffsets" |
| 23 }; |
| 24 return kArrayNames[coords]; |
| 25 |
| 26 GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates); |
| 27 GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates); |
| 28 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLa
st_Coordinates + 1); |
| 29 } |
| 30 |
19 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { | 31 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { |
20 SkASSERT(GrBlendEquationIsAdvanced(equation)); | 32 SkASSERT(GrBlendEquationIsAdvanced(equation)); |
21 | 33 |
22 static const char* kLayoutQualifierNames[] = { | 34 static const char* kLayoutQualifierNames[] = { |
23 "blend_support_screen", | 35 "blend_support_screen", |
24 "blend_support_overlay", | 36 "blend_support_overlay", |
25 "blend_support_darken", | 37 "blend_support_darken", |
26 "blend_support_lighten", | 38 "blend_support_lighten", |
27 "blend_support_colordodge", | 39 "blend_support_colordodge", |
28 "blend_support_colorburn", | 40 "blend_support_colorburn", |
(...skipping 21 matching lines...) Expand all Loading... |
50 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); | 62 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); |
51 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); | 63 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); |
52 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquati
on); | 64 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquati
on); |
53 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); | 65 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); |
54 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); | 66 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); |
55 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); | 67 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); |
56 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) == | 68 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) == |
57 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); | 69 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); |
58 } | 70 } |
59 | 71 |
60 GrGLSLFragmentShaderBuilder::FragPosKey | 72 uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin)
{ |
61 GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { | 73 SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin =
= origin); |
62 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { | 74 return origin; |
63 return kTopLeftFragPosRead_FragPosKey; | 75 |
64 } else { | 76 GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin); |
65 return kBottomLeftFragPosRead_FragPosKey; | 77 GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin); |
66 } | |
67 } | 78 } |
68 | 79 |
69 GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
rogram, | 80 GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
rogram) |
70 uint8_t fragPosKey) | |
71 : GrGLSLFragmentBuilder(program) | 81 : GrGLSLFragmentBuilder(program) |
72 , fSetupFragPosition(false) | 82 , fSetupFragPosition(false) |
73 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) | |
74 , fHasCustomColorOutput(false) | 83 , fHasCustomColorOutput(false) |
75 , fCustomColorOutputIndex(-1) | 84 , fCustomColorOutputIndex(-1) |
76 , fHasSecondaryOutput(false) | 85 , fHasSecondaryOutput(false) |
| 86 , fUsedSampleOffsetArrays(0) |
77 , fHasInitializedSampleMask(false) { | 87 , fHasInitializedSampleMask(false) { |
78 fSubstageIndices.push_back(0); | 88 fSubstageIndices.push_back(0); |
79 #ifdef SK_DEBUG | 89 #ifdef SK_DEBUG |
80 fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures; | 90 fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures; |
81 fHasReadDstColor = false; | 91 fHasReadDstColor = false; |
82 #endif | 92 #endif |
83 } | 93 } |
84 | 94 |
85 bool GrGLSLFragmentShaderBuilder::hasFragmentPosition() const { | |
86 return 0 != fProgramBuilder->header().fFragPosKey; | |
87 } | |
88 | |
89 bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { | 95 bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { |
90 switch (feature) { | 96 switch (feature) { |
91 case kStandardDerivatives_GLSLFeature: { | 97 case kStandardDerivatives_GLSLFeature: { |
92 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) { | 98 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) { |
93 return false; | 99 return false; |
94 } | 100 } |
95 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativ
eExtensionString(); | 101 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativ
eExtensionString(); |
96 if (extension) { | 102 if (extension) { |
97 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extensio
n); | 103 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extensio
n); |
98 } | 104 } |
(...skipping 23 matching lines...) Expand all Loading... |
122 SkString coords2D("coords2D"); | 128 SkString coords2D("coords2D"); |
123 if (0 != index) { | 129 if (0 != index) { |
124 coords2D.appendf("_%i", index); | 130 coords2D.appendf("_%i", index); |
125 } | 131 } |
126 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", | 132 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", |
127 coords2D.c_str(), coords[index].c_str(), coords[index].c_s
tr()); | 133 coords2D.c_str(), coords[index].c_str(), coords[index].c_s
tr()); |
128 return coords2D; | 134 return coords2D; |
129 } | 135 } |
130 | 136 |
131 const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { | 137 const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { |
132 SkASSERT(this->hasFragmentPosition()); | |
133 SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_Require
dFeature;) | 138 SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_Require
dFeature;) |
134 | 139 |
135 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); | 140 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); |
136 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers | 141 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers |
137 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the | 142 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the |
138 // declaration varies in earlier GLSL specs. So it is simpler to omit it. | 143 // declaration varies in earlier GLSL specs. So it is simpler to omit it. |
139 if (fTopLeftFragPosRead) { | 144 if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) { |
140 fSetupFragPosition = true; | 145 fSetupFragPosition = true; |
141 return "gl_FragCoord"; | 146 return "gl_FragCoord"; |
142 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionSt
ring()) { | 147 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionSt
ring()) { |
143 if (!fSetupFragPosition) { | 148 if (!fSetupFragPosition) { |
144 if (glslCaps->generation() < k150_GrGLSLGeneration) { | 149 if (glslCaps->generation() < k150_GrGLSLGeneration) { |
145 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, | 150 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, |
146 extension); | 151 extension); |
147 } | 152 } |
148 fInputs.push_back().set(kVec4f_GrSLType, | 153 fInputs.push_back().set(kVec4f_GrSLType, |
149 GrGLSLShaderVar::kIn_TypeModifier, | 154 GrGLSLShaderVar::kIn_TypeModifier, |
(...skipping 20 matching lines...) Expand all Loading... |
170 this->codePrependf("\t%svec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n
", | 175 this->codePrependf("\t%svec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n
", |
171 precision, kCoordName, kTempName, rtHeightName, k
TempName); | 176 precision, kCoordName, kTempName, rtHeightName, k
TempName); |
172 this->codePrependf("%svec2 %s = gl_FragCoord.xy;", precision, kTempN
ame); | 177 this->codePrependf("%svec2 %s = gl_FragCoord.xy;", precision, kTempN
ame); |
173 fSetupFragPosition = true; | 178 fSetupFragPosition = true; |
174 } | 179 } |
175 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); | 180 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); |
176 return kCoordName; | 181 return kCoordName; |
177 } | 182 } |
178 } | 183 } |
179 | 184 |
| 185 void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Co
ordinates coords) { |
| 186 SkASSERT(fProgramBuilder->header().fSamplePatternKey); |
| 187 SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_Required
Feature); |
| 188 if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) { |
| 189 // With a top left origin, device and window space are equal, so we only
use device coords. |
| 190 coords = kSkiaDevice_Coordinates; |
| 191 } |
| 192 this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx); |
| 193 fUsedSampleOffsetArrays |= (1 << coords); |
| 194 } |
| 195 |
180 void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool inve
rt) { | 196 void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool inve
rt) { |
181 const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps(); | 197 const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps(); |
182 if (!glslCaps.sampleVariablesSupport()) { | 198 if (!glslCaps.sampleVariablesSupport()) { |
183 SkDEBUGFAIL("Attempted to mask sample coverage without support."); | 199 SkDEBUGFAIL("Attempted to mask sample coverage without support."); |
184 return; | 200 return; |
185 } | 201 } |
186 if (const char* extension = glslCaps.sampleVariablesExtensionString()) { | 202 if (const char* extension = glslCaps.sampleVariablesExtensionString()) { |
187 this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension); | 203 this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension); |
188 } | 204 } |
189 if (!fHasInitializedSampleMask) { | 205 if (!fHasInitializedSampleMask) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 inputs().appendVAList(fmt, argp); | 317 inputs().appendVAList(fmt, argp); |
302 va_end(argp); | 318 va_end(argp); |
303 } | 319 } |
304 | 320 |
305 const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const { | 321 const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const { |
306 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); | 322 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); |
307 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutput
Name() | 323 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutput
Name() |
308 : "gl_SecondaryFragColorEXT"; | 324 : "gl_SecondaryFragColorEXT"; |
309 } | 325 } |
310 | 326 |
| 327 GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const { |
| 328 SkASSERT(fProgramBuilder->header().fSurfaceOriginKey); |
| 329 return static_cast<GrSurfaceOrigin>(fProgramBuilder->header().fSurfaceOrigin
Key); |
| 330 |
| 331 GR_STATIC_ASSERT(1 == kTopLeft_GrSurfaceOrigin); |
| 332 GR_STATIC_ASSERT(2 == kBottomLeft_GrSurfaceOrigin); |
| 333 } |
| 334 |
311 void GrGLSLFragmentShaderBuilder::onFinalize() { | 335 void GrGLSLFragmentShaderBuilder::onFinalize() { |
312 fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outp
uts()); | 336 fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outp
uts()); |
313 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, | 337 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, |
314 *fProgramBuilder->glslCaps(), | 338 *fProgramBuilder->glslCaps(), |
315 &this->precisionQualifier()); | 339 &this->precisionQualifier()); |
| 340 if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) { |
| 341 this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coord
inates), |
| 342 SkMatrix::MakeTrans(-0.5f, -0.5f)); |
| 343 } |
| 344 if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) { |
| 345 // With a top left origin, device and window space are equal, so we only
use device coords. |
| 346 SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin()); |
| 347 SkMatrix m; |
| 348 m.setScale(1, -1); |
| 349 m.preTranslate(-0.5f, -0.5f); |
| 350 this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coord
inates), m); |
| 351 } |
| 352 } |
| 353 |
| 354 void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, cons
t SkMatrix& m) { |
| 355 SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport()); |
| 356 const GrCaps::MultisampleSpecs& specs = |
| 357 fProgramBuilder->caps()->getMultisampleSpecs(fProgramBuilder->header().f
SamplePatternKey); |
| 358 SkSTArray<16, SkPoint, true> offsets; |
| 359 offsets.push_back_n(specs.fEffectiveSampleCnt); |
| 360 m.mapPoints(offsets.begin(), specs.fSampleLocations.get(), specs.fEffectiveS
ampleCnt); |
| 361 this->definitions().append("const "); |
| 362 if (fProgramBuilder->glslCaps()->usesPrecisionModifiers()) { |
| 363 this->definitions().append("highp "); |
| 364 } |
| 365 this->definitions().appendf("vec2 %s[] = vec2[](", name); |
| 366 for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) { |
| 367 this->definitions().appendf("vec2(%f, %f)", offsets[i].x(), offsets[i].y
()); |
| 368 this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : "
);\n"); |
| 369 } |
316 } | 370 } |
317 | 371 |
318 void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() { | 372 void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() { |
319 SkASSERT(fSubstageIndices.count() >= 1); | 373 SkASSERT(fSubstageIndices.count() >= 1); |
320 fSubstageIndices.push_back(0); | 374 fSubstageIndices.push_back(0); |
321 // second-to-last value in the fSubstageIndices stack is the index of the ch
ild proc | 375 // second-to-last value in the fSubstageIndices stack is the index of the ch
ild proc |
322 // at that level which is currently emitting code. | 376 // at that level which is currently emitting code. |
323 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]
); | 377 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]
); |
324 } | 378 } |
325 | 379 |
326 void GrGLSLFragmentShaderBuilder::onAfterChildProcEmitCode() { | 380 void GrGLSLFragmentShaderBuilder::onAfterChildProcEmitCode() { |
327 SkASSERT(fSubstageIndices.count() >= 2); | 381 SkASSERT(fSubstageIndices.count() >= 2); |
328 fSubstageIndices.pop_back(); | 382 fSubstageIndices.pop_back(); |
329 fSubstageIndices.back()++; | 383 fSubstageIndices.back()++; |
330 int removeAt = fMangleString.findLastOf('_'); | 384 int removeAt = fMangleString.findLastOf('_'); |
331 fMangleString.remove(removeAt, fMangleString.size() - removeAt); | 385 fMangleString.remove(removeAt, fMangleString.size() - removeAt); |
332 } | 386 } |
333 | 387 |
OLD | NEW |