| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrDistanceFieldGeoProc.h" | 8 #include "GrDistanceFieldGeoProc.h" |
| 9 #include "GrInvariantOutput.h" | 9 #include "GrInvariantOutput.h" |
| 10 #include "GrTexture.h" | 10 #include "GrTexture.h" |
| 11 | 11 |
| 12 #include "SkDistanceFieldGen.h" | 12 #include "SkDistanceFieldGen.h" |
| 13 | 13 |
| 14 #include "gl/GrGLFragmentProcessor.h" | 14 #include "gl/GrGLFragmentProcessor.h" |
| 15 #include "gl/GrGLTexture.h" | 15 #include "gl/GrGLTexture.h" |
| 16 #include "gl/GrGLGeometryProcessor.h" | 16 #include "gl/GrGLGeometryProcessor.h" |
| 17 #include "gl/builders/GrGLProgramBuilder.h" | 17 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 18 #include "glsl/GrGLSLProgramBuilder.h" |
| 18 #include "glsl/GrGLSLProgramDataManager.h" | 19 #include "glsl/GrGLSLProgramDataManager.h" |
| 20 #include "glsl/GrGLSLVertexShaderBuilder.h" |
| 19 | 21 |
| 20 // Assuming a radius of a little less than the diagonal of the fragment | 22 // Assuming a radius of a little less than the diagonal of the fragment |
| 21 #define SK_DistanceFieldAAFactor "0.65" | 23 #define SK_DistanceFieldAAFactor "0.65" |
| 22 | 24 |
| 23 class GrGLDistanceFieldA8TextGeoProc : public GrGLGeometryProcessor { | 25 class GrGLDistanceFieldA8TextGeoProc : public GrGLGeometryProcessor { |
| 24 public: | 26 public: |
| 25 GrGLDistanceFieldA8TextGeoProc() | 27 GrGLDistanceFieldA8TextGeoProc() |
| 26 : fViewMatrix(SkMatrix::InvalidMatrix()) | 28 : fViewMatrix(SkMatrix::InvalidMatrix()) |
| 27 , fColor(GrColor_ILLEGAL) | 29 , fColor(GrColor_ILLEGAL) |
| 28 #ifdef SK_GAMMA_APPLY_TO_A8 | 30 #ifdef SK_GAMMA_APPLY_TO_A8 |
| 29 , fDistanceAdjust(-1.0f) | 31 , fDistanceAdjust(-1.0f) |
| 30 #endif | 32 #endif |
| 31 {} | 33 {} |
| 32 | 34 |
| 33 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ | 35 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ |
| 34 const GrDistanceFieldA8TextGeoProc& dfTexEffect = | 36 const GrDistanceFieldA8TextGeoProc& dfTexEffect = |
| 35 args.fGP.cast<GrDistanceFieldA8TextGeoProc>(); | 37 args.fGP.cast<GrDistanceFieldA8TextGeoProc>(); |
| 36 GrGLSLGPBuilder* pb = args.fPB; | 38 GrGLSLGPBuilder* pb = args.fPB; |
| 37 GrGLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); | 39 GrGLSLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); |
| 38 SkAssertResult(fsBuilder->enableFeature( | 40 SkAssertResult(fsBuilder->enableFeature( |
| 39 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); | 41 GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); |
| 40 | 42 |
| 41 GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); | 43 GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); |
| 42 | 44 |
| 43 // emit attributes | 45 // emit attributes |
| 44 vsBuilder->emitAttributes(dfTexEffect); | 46 vsBuilder->emitAttributes(dfTexEffect); |
| 45 | 47 |
| 46 #ifdef SK_GAMMA_APPLY_TO_A8 | 48 #ifdef SK_GAMMA_APPLY_TO_A8 |
| 47 // adjust based on gamma | 49 // adjust based on gamma |
| 48 const char* distanceAdjustUniName = nullptr; | 50 const char* distanceAdjustUniName = nullptr; |
| 49 // width, height, 1/(3*width) | 51 // width, height, 1/(3*width) |
| 50 fDistanceAdjustUni = pb->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, | 52 fDistanceAdjustUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visi
bility, |
| 51 kFloat_GrSLType, kDefault_GrSLPrecision, | 53 kFloat_GrSLType, kDefault_GrSLPrecision, |
| 52 "DistanceAdjust", &distanceAdjustUniName); | 54 "DistanceAdjust", &distanceAdjustUniName); |
| 53 #endif | 55 #endif |
| 54 | 56 |
| 55 // Setup pass through color | 57 // Setup pass through color |
| 56 if (!dfTexEffect.colorIgnored()) { | 58 if (!dfTexEffect.colorIgnored()) { |
| 57 if (dfTexEffect.hasVertexColor()) { | 59 if (dfTexEffect.hasVertexColor()) { |
| 58 pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputC
olor); | 60 pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputC
olor); |
| 59 } else { | 61 } else { |
| 60 this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); | 62 this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 public: | 280 public: |
| 279 GrGLDistanceFieldPathGeoProc() | 281 GrGLDistanceFieldPathGeoProc() |
| 280 : fViewMatrix(SkMatrix::InvalidMatrix()) | 282 : fViewMatrix(SkMatrix::InvalidMatrix()) |
| 281 , fColor(GrColor_ILLEGAL) | 283 , fColor(GrColor_ILLEGAL) |
| 282 , fTextureSize(SkISize::Make(-1, -1)) {} | 284 , fTextureSize(SkISize::Make(-1, -1)) {} |
| 283 | 285 |
| 284 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ | 286 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ |
| 285 const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistance
FieldPathGeoProc>(); | 287 const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistance
FieldPathGeoProc>(); |
| 286 | 288 |
| 287 GrGLSLGPBuilder* pb = args.fPB; | 289 GrGLSLGPBuilder* pb = args.fPB; |
| 288 GrGLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); | 290 GrGLSLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); |
| 289 SkAssertResult(fsBuilder->enableFeature( | 291 SkAssertResult(fsBuilder->enableFeature( |
| 290 GrGLFragmentShaderBuilder::kStandardDerivat
ives_GLSLFeature)); | 292 GrGLSLFragmentShaderBuilder::kStandardDeriv
atives_GLSLFeature)); |
| 291 | 293 |
| 292 GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); | 294 GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); |
| 293 | 295 |
| 294 // emit attributes | 296 // emit attributes |
| 295 vsBuilder->emitAttributes(dfTexEffect); | 297 vsBuilder->emitAttributes(dfTexEffect); |
| 296 | 298 |
| 297 GrGLSLVertToFrag v(kVec2f_GrSLType); | 299 GrGLSLVertToFrag v(kVec2f_GrSLType); |
| 298 pb->addVarying("TextureCoords", &v, kHigh_GrSLPrecision); | 300 pb->addVarying("TextureCoords", &v, kHigh_GrSLPrecision); |
| 299 | 301 |
| 300 // setup pass through color | 302 // setup pass through color |
| 301 if (!dfTexEffect.colorIgnored()) { | 303 if (!dfTexEffect.colorIgnored()) { |
| 302 if (dfTexEffect.hasVertexColor()) { | 304 if (dfTexEffect.hasVertexColor()) { |
| 303 pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputC
olor); | 305 pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputC
olor); |
| 304 } else { | 306 } else { |
| 305 this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); | 307 this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); |
| 306 } | 308 } |
| 307 } | 309 } |
| 308 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoord
s()->fName); | 310 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoord
s()->fName); |
| 309 | 311 |
| 310 // Setup position | 312 // Setup position |
| 311 this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEf
fect.viewMatrix(), | 313 this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEf
fect.viewMatrix(), |
| 312 &fViewMatrixUniform); | 314 &fViewMatrixUniform); |
| 313 | 315 |
| 314 // emit transforms | 316 // emit transforms |
| 315 this->emitTransforms(pb, gpArgs->fPositionVar, dfTexEffect.inPosition()-
>fName, | 317 this->emitTransforms(pb, gpArgs->fPositionVar, dfTexEffect.inPosition()-
>fName, |
| 316 args.fTransformsIn, args.fTransformsOut); | 318 args.fTransformsIn, args.fTransformsOut); |
| 317 | 319 |
| 318 const char* textureSizeUniName = nullptr; | 320 const char* textureSizeUniName = nullptr; |
| 319 fTextureSizeUni = pb->addUniform(GrGLProgramBuilder::kFragment_Visibilit
y, | 321 fTextureSizeUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibil
ity, |
| 320 kVec2f_GrSLType, kDefault_GrSLPrecision
, | 322 kVec2f_GrSLType, kDefault_GrSLPrecision
, |
| 321 "TextureSize", &textureSizeUniName); | 323 "TextureSize", &textureSizeUniName); |
| 322 | 324 |
| 323 // Use highp to work around aliasing issues | 325 // Use highp to work around aliasing issues |
| 324 fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), | 326 fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), |
| 325 kHigh_GrSLPrecisi
on)); | 327 kHigh_GrSLPrecisi
on)); |
| 326 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); | 328 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); |
| 327 | 329 |
| 328 fsBuilder->codeAppend("float texColor = "); | 330 fsBuilder->codeAppend("float texColor = "); |
| 329 fsBuilder->appendTextureLookup(args.fSamplers[0], | 331 fsBuilder->appendTextureLookup(args.fSamplers[0], |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 GrGLDistanceFieldLCDTextGeoProc() | 496 GrGLDistanceFieldLCDTextGeoProc() |
| 495 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL) { | 497 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL) { |
| 496 fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.
0f, 1.0f, 1.0f); | 498 fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.
0f, 1.0f, 1.0f); |
| 497 } | 499 } |
| 498 | 500 |
| 499 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ | 501 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ |
| 500 const GrDistanceFieldLCDTextGeoProc& dfTexEffect = | 502 const GrDistanceFieldLCDTextGeoProc& dfTexEffect = |
| 501 args.fGP.cast<GrDistanceFieldLCDTextGeoProc>(); | 503 args.fGP.cast<GrDistanceFieldLCDTextGeoProc>(); |
| 502 GrGLSLGPBuilder* pb = args.fPB; | 504 GrGLSLGPBuilder* pb = args.fPB; |
| 503 | 505 |
| 504 GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); | 506 GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); |
| 505 | 507 |
| 506 // emit attributes | 508 // emit attributes |
| 507 vsBuilder->emitAttributes(dfTexEffect); | 509 vsBuilder->emitAttributes(dfTexEffect); |
| 508 | 510 |
| 509 // setup pass through color | 511 // setup pass through color |
| 510 if (!dfTexEffect.colorIgnored()) { | 512 if (!dfTexEffect.colorIgnored()) { |
| 511 this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); | 513 this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); |
| 512 } | 514 } |
| 513 | 515 |
| 514 // Setup position | 516 // Setup position |
| (...skipping 19 matching lines...) Expand all Loading... |
| 534 SkScalar recipHeight = 1.0f / atlas->height(); | 536 SkScalar recipHeight = 1.0f / atlas->height(); |
| 535 | 537 |
| 536 GrGLSLVertToFrag uv(kVec2f_GrSLType); | 538 GrGLSLVertToFrag uv(kVec2f_GrSLType); |
| 537 pb->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); | 539 pb->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); |
| 538 vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(), | 540 vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(), |
| 539 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth, | 541 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth, |
| 540 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight, | 542 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight, |
| 541 dfTexEffect.inTextureCoords()->fName); | 543 dfTexEffect.inTextureCoords()->fName); |
| 542 | 544 |
| 543 // add frag shader code | 545 // add frag shader code |
| 544 GrGLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); | 546 GrGLSLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); |
| 545 | 547 |
| 546 SkAssertResult(fsBuilder->enableFeature( | 548 SkAssertResult(fsBuilder->enableFeature( |
| 547 GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); | 549 GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); |
| 548 | 550 |
| 549 // create LCD offset adjusted by inverse of transform | 551 // create LCD offset adjusted by inverse of transform |
| 550 // Use highp to work around aliasing issues | 552 // Use highp to work around aliasing issues |
| 551 fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), | 553 fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), |
| 552 kHigh_GrSLPrecisi
on)); | 554 kHigh_GrSLPrecisi
on)); |
| 553 fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); | 555 fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); |
| 554 fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), | 556 fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), |
| 555 kHigh_GrSLPrecisi
on)); | 557 kHigh_GrSLPrecisi
on)); |
| 556 | 558 |
| 557 SkScalar lcdDelta = 1.0f / (3.0f * atlas->width()); | 559 SkScalar lcdDelta = 1.0f / (3.0f * atlas->width()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 588 fsBuilder->codeAppend("\ttexColor = "); | 590 fsBuilder->codeAppend("\ttexColor = "); |
| 589 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_
GrSLType); | 591 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_
GrSLType); |
| 590 fsBuilder->codeAppend(";\n"); | 592 fsBuilder->codeAppend(";\n"); |
| 591 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); | 593 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); |
| 592 | 594 |
| 593 fsBuilder->codeAppend("\tdistance = " | 595 fsBuilder->codeAppend("\tdistance = " |
| 594 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceF
ieldThreshold"));"); | 596 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceF
ieldThreshold"));"); |
| 595 | 597 |
| 596 // adjust width based on gamma | 598 // adjust width based on gamma |
| 597 const char* distanceAdjustUniName = nullptr; | 599 const char* distanceAdjustUniName = nullptr; |
| 598 fDistanceAdjustUni = pb->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, | 600 fDistanceAdjustUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visi
bility, |
| 599 kVec3f_GrSLType, kDefault_GrSLPrecision, | 601 kVec3f_GrSLType, kDefault_GrSLPrecision, |
| 600 "DistanceAdjust", &distanceAdjustUniName); | 602 "DistanceAdjust", &distanceAdjustUniName); |
| 601 fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); | 603 fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); |
| 602 | 604 |
| 603 // To be strictly correct, we should compute the anti-aliasing factor se
parately | 605 // To be strictly correct, we should compute the anti-aliasing factor se
parately |
| 604 // for each color component. However, this is only important when using
perspective | 606 // for each color component. However, this is only important when using
perspective |
| 605 // transformations, and even then using a single factor seems like a rea
sonable | 607 // transformations, and even then using a single factor seems like a rea
sonable |
| 606 // trade-off between quality and speed. | 608 // trade-off between quality and speed. |
| 607 fsBuilder->codeAppend("float afwidth;"); | 609 fsBuilder->codeAppend("float afwidth;"); |
| 608 if (isUniformScale) { | 610 if (isUniformScale) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; | 753 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; |
| 752 flags |= d->fRandom->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; | 754 flags |= d->fRandom->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; |
| 753 flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; | 755 flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; |
| 754 return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), | 756 return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), |
| 755 GrTest::TestMatrix(d->fRandom), | 757 GrTest::TestMatrix(d->fRandom), |
| 756 d->fTextures[texIdx], params, | 758 d->fTextures[texIdx], params, |
| 757 wa, | 759 wa, |
| 758 flags, | 760 flags, |
| 759 d->fRandom->nextBool()); | 761 d->fRandom->nextBool()); |
| 760 } | 762 } |
| OLD | NEW |