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