1d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/* 2d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * Copyright 2013 Google Inc. 3d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * 4d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * Use of this source code is governed by a BSD-style license that can be 5d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com * found in the LICENSE file. 6d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com */ 7d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 88ed3b9a386374d7996dfbe0c9de13b42f3dd245djvanverth#include "GrDistanceFieldGeoProc.h" 9605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h" 10eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrTexture.h" 1121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 12eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkDistanceFieldGen.h" 1321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 142d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 15e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h" 16018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 177ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 1864c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLUtil.h" 190eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel#include "glsl/GrGLSLVarying.h" 200eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel#include "glsl/GrGLSLVertexShaderBuilder.h" 21d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 2221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth// Assuming a radius of a little less than the diagonal of the fragment 2324ba00825092be0d400074e0121ffc7221950dd9jvanverth#define SK_DistanceFieldAAFactor "0.65" 242d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 25e659a581f63fdccb64dce2dc8a478cf56831feeaegdanielclass GrGLDistanceFieldA8TextGeoProc : public GrGLSLGeometryProcessor { 26d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.compublic: 27465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldA8TextGeoProc() 285559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt : fViewMatrix(SkMatrix::InvalidMatrix()) 299564ce60a657acce89fb956deb8645b324eaad1ejvanverth#ifdef SK_GAMMA_APPLY_TO_A8 3021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(-1.0f) 319564ce60a657acce89fb956deb8645b324eaad1ejvanverth#endif 329564ce60a657acce89fb956deb8645b324eaad1ejvanverth {} 33d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 3436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 35502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = 36502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth args.fGP.cast<GrDistanceFieldA8TextGeoProc>(); 378528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 384ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel SkAssertResult(fragBuilder->enableFeature( 392d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 406c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 414ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 420eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 437ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 44abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 45abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 460eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->emitAttributes(dfTexEffect); 47abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 4821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 4921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust based on gamma 5096fcdcc219d2a0d3579719b84b28bede76efba64halcanary const char* distanceAdjustUniName = nullptr; 5121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // width, height, 1/(3*width) 525e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 537ea439b2203855db97330b25945b87dd4b170b8begdaniel kFloat_GrSLType, kDefault_GrSLPrecision, 547ea439b2203855db97330b25945b87dd4b170b8begdaniel "DistanceAdjust", &distanceAdjustUniName); 5521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif 56d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 579b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // Setup pass through color 58b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (!dfTexEffect.colorIgnored()) { 5953f26aa045d58feb9f2114f53629024bffe52deajoshualitt varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); 60b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 616c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 62abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 637ea439b2203855db97330b25945b87dd4b170b8begdaniel this->setupPosition(vertBuilder, 647ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 654ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs, 664ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inPosition()->fName, 674ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.viewMatrix(), 685559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 694973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 70abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 717ea439b2203855db97330b25945b87dd4b170b8begdaniel this->emitTransforms(vertBuilder, 720eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler, 737ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 744ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs->fPositionVar, 754ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inPosition()->fName, 764ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel args.fTransformsIn, 774ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel args.fTransformsOut); 78abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 79bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // add varyings 808dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag recipScale(kFloat_GrSLType); 817023a00c35d904e4ccff09c377e9ba26abba6181jvanverth GrGLSLVertToFrag uv(kVec2f_GrSLType); 82bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); 837023a00c35d904e4ccff09c377e9ba26abba6181jvanverth varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); 847023a00c35d904e4ccff09c377e9ba26abba6181jvanverth vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName); 85bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 86922c8b13c512c3287509936795735c1b31bedba9joshualitt // compute numbers to be hardcoded to convert texture coordinates from int to float 87922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(dfTexEffect.numTextures() == 1); 88922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); 897375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height())); 90922c8b13c512c3287509936795735c1b31bedba9joshualitt 917023a00c35d904e4ccff09c377e9ba26abba6181jvanverth GrGLSLVertToFrag st(kVec2f_GrSLType); 927023a00c35d904e4ccff09c377e9ba26abba6181jvanverth varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); 937023a00c35d904e4ccff09c377e9ba26abba6181jvanverth vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(), 947023a00c35d904e4ccff09c377e9ba26abba6181jvanverth atlas->width(), atlas->height(), 954ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inTextureCoords()->fName); 96bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 97fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 98a2e3e0f7f8ceed2ab152428d7ee2812ad8c842c3egdaniel fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, 994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kHigh_GrSLPrecision)); 1004ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 1014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1024ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tfloat texColor = "); 1034ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(args.fSamplers[0], 1044ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel "uv", 1054ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kVec2f_GrSLType); 1064ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(".r;\n"); 1074ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tfloat distance = " 108fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 10921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 11021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust width based on gamma 1114ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); 11221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif 1136c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 1144ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float afwidth;"); 115bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth if (isSimilarity) { 116354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 117354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 118221360a514fb4bfff5b461e83262306b2a0f36afjvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 119354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 1204362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org // this gives us a smooth step across approximately one fragment 121221360a514fb4bfff5b461e83262306b2a0f36afjvanverth // we use y to work around a Mali400 bug in the x direction 1224ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));", 1234ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel st.fsIn()); 1244362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } else { 125354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 126354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 127354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 1284ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));"); 129d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 130d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 1314ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 1324ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 1334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 1344ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("} else {"); 1354ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 1364ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("}"); 1374ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1384ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn()); 1394ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn()); 1404ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 1414ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 1424362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org 1434362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org // this gives us a smooth step across approximately one fragment 1444ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 1454362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } 1464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); 1474d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth 1484ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 149d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com } 150d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 151018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc) override { 1522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 153502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>(); 15421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float distanceAdjust = dfTexEffect.getDistanceAdjust(); 15521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth if (distanceAdjust != fDistanceAdjust) { 15621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth pdman.set1f(fDistanceAdjustUni, distanceAdjust); 15721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjust = distanceAdjust; 1582d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth } 1592d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 160e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>(); 1615559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt 1625559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (!dfa8gp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfa8gp.viewMatrix())) { 1635559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fViewMatrix = dfa8gp.viewMatrix(); 164018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 16564c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 1665559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 1675559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 1686c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org } 169d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 17046d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 171cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 172b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 173502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>(); 1748fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 17553f26aa045d58feb9f2114f53629024bffe52deajoshualitt key |= dfTexEffect.colorIgnored() << 16; 176e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 1778fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 178922c8b13c512c3287509936795735c1b31bedba9joshualitt 179922c8b13c512c3287509936795735c1b31bedba9joshualitt // Currently we hardcode numbers to convert atlas coordinates to normalized floating point 180922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(gp.numTextures() == 1); 181922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = gp.textureAccess(0).getTexture(); 182922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(atlas); 183922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->width()); 184922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->height()); 1854362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } 1864362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org 187d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate: 1885559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 1895559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 19050282b4390dcddcf3b1d51631c0133045ae1f233mtklein#ifdef SK_GAMMA_APPLY_TO_A8 19121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float fDistanceAdjust; 19221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fDistanceAdjustUni; 19350282b4390dcddcf3b1d51631c0133045ae1f233mtklein#endif 1946c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 195e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel typedef GrGLSLGeometryProcessor INHERITED; 196d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}; 197d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 198d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 199d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 200502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color, 2018059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 2022e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrTexture* texture, 2036c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org const GrTextureParams& params, 2042d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 20521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float distanceAdjust, 2062d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 207b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt uint32_t flags, 208b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt bool usesLocalCoords) 209e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 210e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 2112e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 2122d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 21321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(distanceAdjust) 2142d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 215249af15fb82833d2274850c589812b6e69df0033joshualitt , fFlags(flags & kNonLCD_DistanceFieldEffectMask) 21696fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fInColor(nullptr) 217b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fUsesLocalCoords(usesLocalCoords) { 21878f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); 219502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldA8TextGeoProc>(); 220f2539d50f911914af0f80f0092ff8c654869e650senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 221f2539d50f911914af0f80f0092ff8c654869e650senorblanco kHigh_GrSLPrecision)); 22253f26aa045d58feb9f2114f53629024bffe52deajoshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 22371c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 2247023a00c35d904e4ccff09c377e9ba26abba6181jvanverth kVec2us_GrVertexAttribType, 2257023a00c35d904e4ccff09c377e9ba26abba6181jvanverth kHigh_GrSLPrecision)); 226d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com this->addTextureAccess(&fTextureAccess); 227d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 228d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 22957d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrDistanceFieldA8TextGeoProc::getGLSLProcessorKey(const GrGLSLCaps& caps, 23057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 231465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldA8TextGeoProc::GenKey(*this, caps, b); 232eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 233eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 23457d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLPrimitiveProcessor* GrDistanceFieldA8TextGeoProc::createGLSLInstance(const GrGLSLCaps&) const { 235465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt return new GrGLDistanceFieldA8TextGeoProc(); 236d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 237d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 238d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 239d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 240502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc); 241d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 242c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorTestData* d) { 2430067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 2440067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 245d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com static const SkShader::TileMode kTileModes[] = { 246d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kClamp_TileMode, 247d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kRepeat_TileMode, 248d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kMirror_TileMode, 249d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com }; 250d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::TileMode tileModes[] = { 2510067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 2520067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 253d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com }; 2540067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode : 255d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com GrTextureParams::kNone_FilterMode); 256d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 2570067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(d->fRandom), 2580067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTest::TestMatrix(d->fRandom), 2590067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fTextures[texIdx], params, 2602d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 2610067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextF(), 2622d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 2630067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool() ? 264b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kSimilarity_DistanceFieldEffectFlag : 0, 2650067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool()); 266609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 267609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 268609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 269609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 270e659a581f63fdccb64dce2dc8a478cf56831feeaegdanielclass GrGLDistanceFieldPathGeoProc : public GrGLSLGeometryProcessor { 271fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthpublic: 272465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldPathGeoProc() 2735559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt : fViewMatrix(SkMatrix::InvalidMatrix()) 2745559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt , fTextureSize(SkISize::Make(-1, -1)) {} 275fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 27636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 277502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>(); 278fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 2798528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 2804ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel SkAssertResult(fragBuilder->enableFeature( 2812d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 282fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 2834ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 2840eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 2857ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 286abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 287abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 2880eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->emitAttributes(dfTexEffect); 289abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 2908dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag v(kVec2f_GrSLType); 2910eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->addVarying("TextureCoords", &v, kHigh_GrSLPrecision); 292fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 2939b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // setup pass through color 294b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (!dfTexEffect.colorIgnored()) { 29553f26aa045d58feb9f2114f53629024bffe52deajoshualitt varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); 296b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 2974ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel vertBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName); 298e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed 299abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 3007ea439b2203855db97330b25945b87dd4b170b8begdaniel this->setupPosition(vertBuilder, 3017ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 3024ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs, 3034ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inPosition()->fName, 3044ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.viewMatrix(), 3055559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 306abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 307abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 3087ea439b2203855db97330b25945b87dd4b170b8begdaniel this->emitTransforms(vertBuilder, 3090eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler, 3107ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 3114ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs->fPositionVar, 3124ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inPosition()->fName, 3134ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel args.fTransformsIn, 3144ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel args.fTransformsOut); 3154973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 31696fcdcc219d2a0d3579719b84b28bede76efba64halcanary const char* textureSizeUniName = nullptr; 3175e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fTextureSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 3187ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 3197ea439b2203855db97330b25945b87dd4b170b8begdaniel "TextureSize", &textureSizeUniName); 320e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed 321fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 322a2e3e0f7f8ceed2ab152428d7ee2812ad8c842c3egdaniel fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, 3234ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kHigh_GrSLPrecision)); 3244ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); 3254ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 3264ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float texColor = "); 3274ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(args.fSamplers[0], 3284ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel "uv", 3294ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kVec2f_GrSLType); 3304ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(".r;"); 3314ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float distance = " 332fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 333fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 334a2e3e0f7f8ceed2ab152428d7ee2812ad8c842c3egdaniel fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, 3354ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kHigh_GrSLPrecision)); 3364ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); 3374ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float afwidth;"); 338fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { 339354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 340354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 341354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 342354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 343fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth // this gives us a smooth step across approximately one fragment 3444ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));"); 345fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } else { 346354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 347354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 348354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 3494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));"); 350d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 351d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 3524ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 3534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 3544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 3554ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("} else {"); 3564ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 3574ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("}"); 3584ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 3594ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 3604ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 3614ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 3624ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 363fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 364fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth // this gives us a smooth step across approximately one fragment 3654ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 366fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 3674ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); 368fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3694ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 370fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 371fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 372018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc) override { 373e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkASSERT(fTextureSizeUni.isValid()); 374fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 37587f48d997ec29e5eeaa7567355775e93465dd60djoshualitt GrTexture* texture = proc.texture(0); 376fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth if (texture->width() != fTextureSize.width() || 377fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth texture->height() != fTextureSize.height()) { 378fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fTextureSize = SkISize::Make(texture->width(), texture->height()); 379e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed pdman.set2f(fTextureSizeUni, 380e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkIntToScalar(fTextureSize.width()), 381e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkIntToScalar(fTextureSize.height())); 382fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 3839b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 384e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>(); 3855559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt 3865559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (!dfpgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfpgp.viewMatrix())) { 3875559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fViewMatrix = dfpgp.viewMatrix(); 388018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 38964c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 3905559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 3915559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 392fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 393fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 39446d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 395cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 396fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth GrProcessorKeyBuilder* b) { 397502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>(); 398fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3998fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 400b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.colorIgnored() << 16; 401e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 4028fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 403fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 404fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 405fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthprivate: 406e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed UniformHandle fTextureSizeUni; 4075559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 4085559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 4099b98932adaceb7ad0a617ade16616923f6bffe84joshualitt SkISize fTextureSize; 410fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 411e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel typedef GrGLSLGeometryProcessor INHERITED; 412fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}; 413fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 414fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 415fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 416502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc( 4172e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrColor color, 4188059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 4192e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrTexture* texture, 4202e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt const GrTextureParams& params, 421b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt uint32_t flags, 422b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt bool usesLocalCoords) 423e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 424e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 4252e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 426fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth , fFlags(flags & kNonLCD_DistanceFieldEffectMask) 42796fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fInColor(nullptr) 428b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fUsesLocalCoords(usesLocalCoords) { 429fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); 430502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldPathGeoProc>(); 431f2539d50f911914af0f80f0092ff8c654869e650senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 432f2539d50f911914af0f80f0092ff8c654869e650senorblanco kHigh_GrSLPrecision)); 43353f26aa045d58feb9f2114f53629024bffe52deajoshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 43471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 435b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kVec2f_GrVertexAttribType)); 436fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth this->addTextureAccess(&fTextureAccess); 437fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 438fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 43957d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrDistanceFieldPathGeoProc::getGLSLProcessorKey(const GrGLSLCaps& caps, 44057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 441465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldPathGeoProc::GenKey(*this, caps, b); 442eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 443eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 44457d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLPrimitiveProcessor* GrDistanceFieldPathGeoProc::createGLSLInstance(const GrGLSLCaps&) const { 445465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt return new GrGLDistanceFieldPathGeoProc(); 446fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 447fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 448fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 449fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 450502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc); 451fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 452c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* d) { 4530067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx 4540067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt : GrProcessorUnitTest::kAlphaTextureIdx; 455fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth static const SkShader::TileMode kTileModes[] = { 456fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kClamp_TileMode, 457fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kRepeat_TileMode, 458fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kMirror_TileMode, 459fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth }; 460fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::TileMode tileModes[] = { 4610067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 4620067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 463fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth }; 4640067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode 4650067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt : GrTextureParams::kNone_FilterMode); 466fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 4670067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrDistanceFieldPathGeoProc::Create(GrRandomColor(d->fRandom), 4680067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTest::TestMatrix(d->fRandom), 4690067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fTextures[texIdx], 470502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth params, 4710067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool() ? 472b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kSimilarity_DistanceFieldEffectFlag : 0, 4730067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool()); 474fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 475fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 476fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 477fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 478e659a581f63fdccb64dce2dc8a478cf56831feeaegdanielclass GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor { 479609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic: 480465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldLCDTextGeoProc() 48153f26aa045d58feb9f2114f53629024bffe52deajoshualitt : fViewMatrix(SkMatrix::InvalidMatrix()) { 482502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f); 48321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth } 484609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 48536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 486502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = 487502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth args.fGP.cast<GrDistanceFieldLCDTextGeoProc>(); 488609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 4894ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 4900eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 4917ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 492abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 493abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 4940eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->emitAttributes(dfTexEffect); 4954ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 4968528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 497abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 4989b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // setup pass through color 499b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (!dfTexEffect.colorIgnored()) { 50053f26aa045d58feb9f2114f53629024bffe52deajoshualitt varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); 501b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 5029b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 503abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 5047ea439b2203855db97330b25945b87dd4b170b8begdaniel this->setupPosition(vertBuilder, 5057ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 5064ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs, 5074ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inPosition()->fName, 5084ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.viewMatrix(), 5095559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 5104973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 511abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 5127ea439b2203855db97330b25945b87dd4b170b8begdaniel this->emitTransforms(vertBuilder, 5130eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler, 5147ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 5154ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs->fPositionVar, 5164ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inPosition()->fName, 5174ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel args.fTransformsIn, 5184ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel args.fTransformsOut); 5195b143038cb47763974d2750ed78d436eb6c38beajvanverth 520bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // set up varyings 521bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); 5228dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag recipScale(kFloat_GrSLType); 5237023a00c35d904e4ccff09c377e9ba26abba6181jvanverth GrGLSLVertToFrag uv(kVec2f_GrSLType); 5247023a00c35d904e4ccff09c377e9ba26abba6181jvanverth varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); 5257023a00c35d904e4ccff09c377e9ba26abba6181jvanverth vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName); 526bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 527922c8b13c512c3287509936795735c1b31bedba9joshualitt // compute numbers to be hardcoded to convert texture coordinates from int to float 528922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(dfTexEffect.numTextures() == 1); 529922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); 5307375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height())); 531922c8b13c512c3287509936795735c1b31bedba9joshualitt 5327023a00c35d904e4ccff09c377e9ba26abba6181jvanverth GrGLSLVertToFrag st(kVec2f_GrSLType); 5337023a00c35d904e4ccff09c377e9ba26abba6181jvanverth varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); 5347023a00c35d904e4ccff09c377e9ba26abba6181jvanverth vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(), 5357023a00c35d904e4ccff09c377e9ba26abba6181jvanverth atlas->width(), atlas->height(), 5364ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel dfTexEffect.inTextureCoords()->fName); 537bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 538bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // add frag shader code 53930ba436f04e61d4505fb854d5fc56079636e0788joshualitt 5404ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel SkAssertResult(fragBuilder->enableFeature( 5412d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 54230ba436f04e61d4505fb854d5fc56079636e0788joshualitt 543609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // create LCD offset adjusted by inverse of transform 544fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 545a2e3e0f7f8ceed2ab152428d7ee2812ad8c842c3egdaniel fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, 5464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kHigh_GrSLPrecision)); 5474ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 548a2e3e0f7f8ceed2ab152428d7ee2812ad8c842c3egdaniel fragBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(args.fGLSLCaps, 5494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel kHigh_GrSLPrecision)); 550922c8b13c512c3287509936795735c1b31bedba9joshualitt 551922c8b13c512c3287509936795735c1b31bedba9joshualitt SkScalar lcdDelta = 1.0f / (3.0f * atlas->width()); 5525a105ff05303ac82a867b8b84a1edd145bd46218jvanverth if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { 5534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float delta = -%.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta); 5545a105ff05303ac82a867b8b84a1edd145bd46218jvanverth } else { 5554ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float delta = %.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta); 5565a105ff05303ac82a867b8b84a1edd145bd46218jvanverth } 55778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth if (isUniformScale) { 5584ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("float dy = abs(dFdy(%s.y));", st.fsIn()); 5594ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 offset = vec2(dy*delta, 0.0);"); 560609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } else { 5614ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); 562bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 5634ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 5644ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 5654ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 offset = delta*Jdx;"); 566609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 567609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 568609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // green is distance to uv center 5694ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tvec4 texColor = "); 5704ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType); 5714ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(";\n"); 5724ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tvec3 distance;\n"); 5734ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tdistance.y = texColor.r;\n"); 574609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // red is distance to left offset 5754ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n"); 5764ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\ttexColor = "); 5774ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType); 5784ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(";\n"); 5794ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tdistance.x = texColor.r;\n"); 580609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // blue is distance to right offset 5814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); 5824ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\ttexColor = "); 5834ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType); 5844ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(";\n"); 5854ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tdistance.z = texColor.r;\n"); 5862d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 5874ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\tdistance = " 588ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));"); 5892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 59021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust width based on gamma 59196fcdcc219d2a0d3579719b84b28bede76efba64halcanary const char* distanceAdjustUniName = nullptr; 5925e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fDistanceAdjustUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 5937ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec3f_GrSLType, kDefault_GrSLPrecision, 5947ea439b2203855db97330b25945b87dd4b170b8begdaniel "DistanceAdjust", &distanceAdjustUniName); 5954ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); 59621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 597609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // To be strictly correct, we should compute the anti-aliasing factor separately 598609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // for each color component. However, this is only important when using perspective 599609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // transformations, and even then using a single factor seems like a reasonable 600609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // trade-off between quality and speed. 6014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float afwidth;"); 60278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth if (isUniformScale) { 603354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 604354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 605354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 606354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 607609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // this gives us a smooth step across approximately one fragment 6084ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*dy;"); 609609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } else { 610354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 611354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 612354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 6134ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));"); 614d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 615d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 6164ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 6174ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 6184ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 6194ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("} else {"); 6204ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 6214ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("}"); 6224ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 6234ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 624609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 625609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // this gives us a smooth step across approximately one fragment 6264ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 627609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 628609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6294ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend( 63021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);"); 63127b6335c71bccb96206ff0495793433bfa982777egdaniel // set alpha to be max of rgb coverage 6324ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("val.a = max(max(val.r, val.g), val.b);"); 63330ba436f04e61d4505fb854d5fc56079636e0788joshualitt 6344ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = val;", args.fOutputCoverage); 635609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 636609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 637018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void setData(const GrGLSLProgramDataManager& pdman, 638465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt const GrPrimitiveProcessor& processor) override { 63921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth SkASSERT(fDistanceAdjustUni.isValid()); 640609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6415559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt const GrDistanceFieldLCDTextGeoProc& dflcd = processor.cast<GrDistanceFieldLCDTextGeoProc>(); 6425559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dflcd.getDistanceAdjust(); 64321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth if (wa != fDistanceAdjust) { 64421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth pdman.set3f(fDistanceAdjustUni, 64521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fR, 64621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fG, 64721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fB); 64821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjust = wa; 6492d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth } 6509b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 6515559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (!dflcd.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dflcd.viewMatrix())) { 6525559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fViewMatrix = dflcd.viewMatrix(); 653018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 65464c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 6555559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 6565559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 657609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 658609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 65946d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 660cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 661b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 662502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>(); 663609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6648fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 665b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.colorIgnored() << 16; 666e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 6678fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 668922c8b13c512c3287509936795735c1b31bedba9joshualitt 669922c8b13c512c3287509936795735c1b31bedba9joshualitt // Currently we hardcode numbers to convert atlas coordinates to normalized floating point 670922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(gp.numTextures() == 1); 671922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = gp.textureAccess(0).getTexture(); 672922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(atlas); 673922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->width()); 674922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->height()); 675609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 676609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 677609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate: 6785559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 6795559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 68021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fColorUniform; 681502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust; 68221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fDistanceAdjustUni; 683609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 684e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel typedef GrGLSLGeometryProcessor INHERITED; 685609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}; 686609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 687609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 688609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 689502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc( 6908059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrColor color, const SkMatrix& viewMatrix, 6912d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth GrTexture* texture, const GrTextureParams& params, 69221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth DistanceAdjust distanceAdjust, 693b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt uint32_t flags, bool usesLocalCoords) 694e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 695e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 6962e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 69721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(distanceAdjust) 698b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fFlags(flags & kLCD_DistanceFieldEffectMask) 699b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fUsesLocalCoords(usesLocalCoords) { 70078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag)); 701502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldLCDTextGeoProc>(); 702f2539d50f911914af0f80f0092ff8c654869e650senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 703f2539d50f911914af0f80f0092ff8c654869e650senorblanco kHigh_GrSLPrecision)); 70453f26aa045d58feb9f2114f53629024bffe52deajoshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 70571c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 7067023a00c35d904e4ccff09c377e9ba26abba6181jvanverth kVec2us_GrVertexAttribType, 7077023a00c35d904e4ccff09c377e9ba26abba6181jvanverth kHigh_GrSLPrecision)); 708609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org this->addTextureAccess(&fTextureAccess); 709609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 710609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 71157d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrDistanceFieldLCDTextGeoProc::getGLSLProcessorKey(const GrGLSLCaps& caps, 71257d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 713465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, caps, b); 714eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 715eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 71657d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLPrimitiveProcessor* GrDistanceFieldLCDTextGeoProc::createGLSLInstance(const GrGLSLCaps&) const { 717465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt return new GrGLDistanceFieldLCDTextGeoProc(); 718609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 719609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 720609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 721609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 722502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc); 723609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 724c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessorTestData* d) { 7250067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 7260067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 727609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org static const SkShader::TileMode kTileModes[] = { 728609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kClamp_TileMode, 729609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kRepeat_TileMode, 730609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kMirror_TileMode, 731609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org }; 732609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::TileMode tileModes[] = { 7330067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 7340067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 735609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org }; 7360067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode : 737609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org GrTextureParams::kNone_FilterMode); 73821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; 73978f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth uint32_t flags = kUseLCD_DistanceFieldEffectFlag; 7400067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt flags |= d->fRandom->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; 7410067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; 7420067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), 7430067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTest::TestMatrix(d->fRandom), 7440067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fTextures[texIdx], params, 745502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth wa, 746b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt flags, 7470067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool()); 748d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 749