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" 95a105ff05303ac82a867b8b84a1edd145bd46218jvanverth#include "GrFontAtlasSizes.h" 10605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdaniel#include "GrInvariantOutput.h" 11eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrTexture.h" 1221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 13eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkDistanceFieldGen.h" 1421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 15b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 16d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLSL.h" 17d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com#include "gl/GrGLTexture.h" 18249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h" 19eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "gl/builders/GrGLProgramBuilder.h" 20d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 2121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth// Assuming a radius of a little less than the diagonal of the fragment 2224ba00825092be0d400074e0121ffc7221950dd9jvanverth#define SK_DistanceFieldAAFactor "0.65" 232d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 249b98932adaceb7ad0a617ade16616923f6bffe84joshualittstruct DistanceFieldBatchTracker { 259b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGPInput fInputColorType; 269b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 27290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt bool fUsesLocalCoords; 289b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}; 299b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 30502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldA8TextGeoProc : public GrGLGeometryProcessor { 31d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.compublic: 32502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrGLDistanceFieldA8TextGeoProc(const GrGeometryProcessor&, 3387f48d997ec29e5eeaa7567355775e93465dd60djoshualitt const GrBatchTracker&) 349b98932adaceb7ad0a617ade16616923f6bffe84joshualitt : fColor(GrColor_ILLEGAL) 359564ce60a657acce89fb956deb8645b324eaad1ejvanverth#ifdef SK_GAMMA_APPLY_TO_A8 3621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(-1.0f) 379564ce60a657acce89fb956deb8645b324eaad1ejvanverth#endif 389564ce60a657acce89fb956deb8645b324eaad1ejvanverth {} 39d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 4036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 41502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = 42502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth args.fGP.cast<GrDistanceFieldA8TextGeoProc>(); 439b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const DistanceFieldBatchTracker& local = args.fBT.cast<DistanceFieldBatchTracker>(); 449b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGLGPBuilder* pb = args.fPB; 4529bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 4630ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkAssertResult(fsBuilder->enableFeature( 4730ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 486c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 492dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); 50abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 51abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 52abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt vsBuilder->emitAttributes(dfTexEffect); 53abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 5421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 5521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust based on gamma 5621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth const char* distanceAdjustUniName = NULL; 5721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // width, height, 1/(3*width) 5821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, 5921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth kFloat_GrSLType, kDefault_GrSLPrecision, 6021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "DistanceAdjust", &distanceAdjustUniName); 6121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif 62d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // Setup pass through color 649b98932adaceb7ad0a617ade16616923f6bffe84joshualitt this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, 659b98932adaceb7ad0a617ade16616923f6bffe84joshualitt dfTexEffect.inColor(), &fColorUniform); 666c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 67abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 68dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); 694973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 70abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 7146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, 72e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt args.fTransformsIn, args.fTransformsOut); 73abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 74bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // add varyings 75bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GrGLVertToFrag recipScale(kFloat_GrSLType); 76bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GrGLVertToFrag st(kVec2f_GrSLType); 77bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); 78221360a514fb4bfff5b461e83262306b2a0f36afjvanverth args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); 79221360a514fb4bfff5b461e83262306b2a0f36afjvanverth vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); 80bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 81bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GrGLVertToFrag uv(kVec2f_GrSLType); 82bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); 83bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // this is only used with text, so our texture bounds always match the glyph atlas 84bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " 85bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), 86bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth dfTexEffect.inTextureCoords()->fName); 87bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 88fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 89fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, 90fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth pb->ctxInfo().standard())); 915a105ff05303ac82a867b8b84a1edd145bd46218jvanverth fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 92fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth 93fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend("\tfloat texColor = "); 94c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], 95fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth "uv", 96d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com kVec2f_GrSLType); 97fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(".r;\n"); 9830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tfloat distance = " 99fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 10021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 10121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust width based on gamma 10221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); 10321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif 1046c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 105354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("float afwidth;"); 106bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth if (isSimilarity) { 107354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 108354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 109221360a514fb4bfff5b461e83262306b2a0f36afjvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 110354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 1114362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org // this gives us a smooth step across approximately one fragment 112221360a514fb4bfff5b461e83262306b2a0f36afjvanverth // we use y to work around a Mali400 bug in the x direction 113221360a514fb4bfff5b461e83262306b2a0f36afjvanverth fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));", 114bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth st.fsIn()); 1154362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } else { 116354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 117354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 118354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 119354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));"); 120d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 121d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 122d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 123d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 124d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 125d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("} else {"); 126d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 127d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("}"); 128d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth 129bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn()); 130bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn()); 131354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 132354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 1334362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org 1344362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org // this gives us a smooth step across approximately one fragment 135354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 1364362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } 137354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); 1384d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth 1392dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 140d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com } 141d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 1427510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen virtual void setData(const GrGLProgramDataManager& pdman, 1439b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const GrPrimitiveProcessor& proc, 14436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const GrBatchTracker& bt) override { 1452d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 146502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>(); 14721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float distanceAdjust = dfTexEffect.getDistanceAdjust(); 14821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth if (distanceAdjust != fDistanceAdjust) { 14921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth pdman.set1f(fDistanceAdjustUni, distanceAdjust); 15021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjust = distanceAdjust; 1512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth } 1522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 1539b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 154e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>(); 155e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt this->setUniformViewMatrix(pdman, dfa8gp.viewMatrix()); 156ee2af95db72152dfa61c841875df0594ca93437djoshualitt 1579b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>(); 1589b98932adaceb7ad0a617ade16616923f6bffe84joshualitt if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { 1599b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGLfloat c[4]; 1609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColorToRGBAFloat(local.fColor, c); 1619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt pdman.set4fv(fColorUniform, 1, c); 1629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt fColor = local.fColor; 1639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt } 1646c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org } 165d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 16646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 1679b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const GrBatchTracker& bt, 168cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 169b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 170502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>(); 1719b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>(); 1728fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 1738fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt key |= local.fInputColorType << 16; 174e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 1758fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 1764362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } 1774362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org 178d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate: 1799b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 1809b98932adaceb7ad0a617ade16616923f6bffe84joshualitt UniformHandle fColorUniform; 18150282b4390dcddcf3b1d51631c0133045ae1f233mtklein#ifdef SK_GAMMA_APPLY_TO_A8 18221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float fDistanceAdjust; 18321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fDistanceAdjustUni; 18450282b4390dcddcf3b1d51631c0133045ae1f233mtklein#endif 1856c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 186249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGLGeometryProcessor INHERITED; 187d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}; 188d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 189d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 190d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 191502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color, 1928059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 1932e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrTexture* texture, 1946c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org const GrTextureParams& params, 1952d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 19621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float distanceAdjust, 1972d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 1981ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt uint32_t flags) 199e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 200e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 2012e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 2022d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 20321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(distanceAdjust) 2042d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 205249af15fb82833d2274850c589812b6e69df0033joshualitt , fFlags(flags & kNonLCD_DistanceFieldEffectMask) 2062dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt , fInColor(NULL) { 20778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); 208502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldA8TextGeoProc>(); 209c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 210c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco kHigh_GrSLPrecision)); 2112dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt if (flags & kColorAttr_DistanceFieldEffectFlag) { 21271c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 2132dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt } 21471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 2155a105ff05303ac82a867b8b84a1edd145bd46218jvanverth kVec2s_GrVertexAttribType)); 216d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com this->addTextureAccess(&fTextureAccess); 217d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 218d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 219502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::getGLProcessorKey(const GrBatchTracker& bt, 220cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps& caps, 221eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrProcessorKeyBuilder* b) const { 222502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrGLDistanceFieldA8TextGeoProc::GenKey(*this, bt, caps, b); 223eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 224eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 225abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor* 226502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::createGLInstance(const GrBatchTracker& bt, 227cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&) const { 228502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth return SkNEW_ARGS(GrGLDistanceFieldA8TextGeoProc, (*this, bt)); 229d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 230d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 231502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldA8TextGeoProc::initBatchTracker(GrBatchTracker* bt, 23221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth const GrPipelineInfo& init) const { 2339b98932adaceb7ad0a617ade16616923f6bffe84joshualitt DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>(); 2349b98932adaceb7ad0a617ade16616923f6bffe84joshualitt local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, 2359b98932adaceb7ad0a617ade16616923f6bffe84joshualitt SkToBool(fInColor)); 236290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt local->fUsesLocalCoords = init.fUsesLocalCoords; 2379b98932adaceb7ad0a617ade16616923f6bffe84joshualitt} 2389b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 239d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 240d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 241502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc); 242d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 243502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(SkRandom* random, 244b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext*, 245b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 246b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture* textures[]) { 247b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 248b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 249d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com static const SkShader::TileMode kTileModes[] = { 250d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kClamp_TileMode, 251d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kRepeat_TileMode, 252d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kMirror_TileMode, 253d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com }; 254d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::TileMode tileModes[] = { 255d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 256d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 257d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com }; 258d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : 259d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com GrTextureParams::kNone_FilterMode); 260d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 261502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(random), 2624eaf9cef5a76098f78efac30beb966ac833d32c2joshualitt GrTest::TestMatrix(random), 2638059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt textures[texIdx], params, 2642d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 2652d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth random->nextF(), 2662d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 26778f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth random->nextBool() ? 2681ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt kSimilarity_DistanceFieldEffectFlag : 0); 269609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 270609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 271609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 272609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 273502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthstruct DistanceFieldPathBatchTracker { 2749b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGPInput fInputColorType; 2759b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 276290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt bool fUsesLocalCoords; 2779b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}; 2789b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 279502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldPathGeoProc : public GrGLGeometryProcessor { 280fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthpublic: 281502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrGLDistanceFieldPathGeoProc(const GrGeometryProcessor&, 28287f48d997ec29e5eeaa7567355775e93465dd60djoshualitt const GrBatchTracker&) 283e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed : fColor(GrColor_ILLEGAL), fTextureSize(SkISize::Make(-1, -1)) {} 284fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 28536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 286502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>(); 287fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 288502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const DistanceFieldPathBatchTracker& local = args.fBT.cast<DistanceFieldPathBatchTracker>(); 2899b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGLGPBuilder* pb = args.fPB; 29029bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 291fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkAssertResult(fsBuilder->enableFeature( 292fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 293fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 2942dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); 295abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 296abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 297abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt vsBuilder->emitAttributes(dfTexEffect); 298abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 299e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed GrGLVertToFrag v(kVec2f_GrSLType); 3009671ecd44e48e8bbe1361830717b79c9c4dc9d17jvanverth args.fPB->addVarying("TextureCoords", &v, kHigh_GrSLPrecision); 301fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3029b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // setup pass through color 3039b98932adaceb7ad0a617ade16616923f6bffe84joshualitt this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, 3049b98932adaceb7ad0a617ade16616923f6bffe84joshualitt dfTexEffect.inColor(), &fColorUniform); 3052dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 306e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName); 307e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed 308abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 309dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); 310abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 311abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 31246d36f0e7b709a077c647841eee23bd3efdc4117robertphillips this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, 313e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt args.fTransformsIn, args.fTransformsOut); 3144973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 315e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed const char* textureSizeUniName = NULL; 316e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed fTextureSizeUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, 317e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed kVec2f_GrSLType, kDefault_GrSLPrecision, 318e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed "TextureSize", &textureSizeUniName); 319e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed 320fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 321fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, 322fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth pb->ctxInfo().standard())); 323e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); 324fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth 325fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend("float texColor = "); 326c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], 327fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth "uv", 328fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth kVec2f_GrSLType); 329fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(".r;"); 330fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("float distance = " 331fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 332fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 333fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, 334fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth pb->ctxInfo().standard())); 335e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); 336fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("float afwidth;"); 337fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { 338354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 339354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 340354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 341354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 342fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth // this gives us a smooth step across approximately one fragment 343bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));"); 344fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } else { 345354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 346354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 347354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 348354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));"); 349d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 350d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 351d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 352d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 353d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 354d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("} else {"); 355d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 356d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("}"); 357d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth 358354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 359354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 360354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 361354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 362fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 363fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth // this gives us a smooth step across approximately one fragment 364fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 365fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 366fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); 367fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3682dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 369fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 370fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 371fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth virtual void setData(const GrGLProgramDataManager& pdman, 3729b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const GrPrimitiveProcessor& proc, 37336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const GrBatchTracker& bt) override { 374e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkASSERT(fTextureSizeUni.isValid()); 375fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 37687f48d997ec29e5eeaa7567355775e93465dd60djoshualitt GrTexture* texture = proc.texture(0); 377fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth if (texture->width() != fTextureSize.width() || 378fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth texture->height() != fTextureSize.height()) { 379fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fTextureSize = SkISize::Make(texture->width(), texture->height()); 380e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed pdman.set2f(fTextureSizeUni, 381e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkIntToScalar(fTextureSize.width()), 382e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkIntToScalar(fTextureSize.height())); 383fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 3849b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 385e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>(); 386e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt this->setUniformViewMatrix(pdman, dfpgp.viewMatrix()); 387ee2af95db72152dfa61c841875df0594ca93437djoshualitt 388502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>(); 3899b98932adaceb7ad0a617ade16616923f6bffe84joshualitt if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { 3909b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGLfloat c[4]; 3919b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColorToRGBAFloat(local.fColor, c); 3929b98932adaceb7ad0a617ade16616923f6bffe84joshualitt pdman.set4fv(fColorUniform, 1, c); 3939b98932adaceb7ad0a617ade16616923f6bffe84joshualitt fColor = local.fColor; 3949b98932adaceb7ad0a617ade16616923f6bffe84joshualitt } 395fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 396fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 39746d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 3989b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const GrBatchTracker& bt, 399cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 400fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth GrProcessorKeyBuilder* b) { 401502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>(); 402fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 403502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const DistanceFieldPathBatchTracker& local = bt.cast<DistanceFieldPathBatchTracker>(); 4048fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 4058fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt key |= local.fInputColorType << 16; 406e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 4078fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 408fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 409fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 410fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthprivate: 4119b98932adaceb7ad0a617ade16616923f6bffe84joshualitt UniformHandle fColorUniform; 412e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed UniformHandle fTextureSizeUni; 4139b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 4149b98932adaceb7ad0a617ade16616923f6bffe84joshualitt SkISize fTextureSize; 415fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 416fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth typedef GrGLGeometryProcessor INHERITED; 417fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}; 418fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 419fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 420fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 421502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc( 4222e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrColor color, 4238059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 4242e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrTexture* texture, 4252e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt const GrTextureParams& params, 4261ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt uint32_t flags) 427e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 428e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 4292e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 430fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth , fFlags(flags & kNonLCD_DistanceFieldEffectMask) 4312dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt , fInColor(NULL) { 432fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); 433502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldPathGeoProc>(); 434c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 435c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco kHigh_GrSLPrecision)); 4362dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt if (flags & kColorAttr_DistanceFieldEffectFlag) { 43771c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 4382dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt } 43971c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 440e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed kVec2f_GrVertexAttribType)); 441fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth this->addTextureAccess(&fTextureAccess); 442fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 443fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 444502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::getGLProcessorKey(const GrBatchTracker& bt, 445cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps& caps, 446502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrProcessorKeyBuilder* b) const { 447502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrGLDistanceFieldPathGeoProc::GenKey(*this, bt, caps, b); 448eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 449eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 450abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor* 451cfc18867d982119d9dc2888bf09f1093012daaddjvanverthGrDistanceFieldPathGeoProc::createGLInstance(const GrBatchTracker& bt, const GrGLSLCaps&) const { 452502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth return SkNEW_ARGS(GrGLDistanceFieldPathGeoProc, (*this, bt)); 453fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 454fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 455502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldPathGeoProc::initBatchTracker(GrBatchTracker* bt, 456502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrPipelineInfo& init) const { 457502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth DistanceFieldPathBatchTracker* local = bt->cast<DistanceFieldPathBatchTracker>(); 4589b98932adaceb7ad0a617ade16616923f6bffe84joshualitt local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, 4599b98932adaceb7ad0a617ade16616923f6bffe84joshualitt SkToBool(fInColor)); 460290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt local->fUsesLocalCoords = init.fUsesLocalCoords; 4619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt} 4629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 463fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 464fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 465502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc); 466fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 467502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(SkRandom* random, 468502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrContext*, 469502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDrawTargetCaps&, 470502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrTexture* textures[]) { 471fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx 472fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth : GrProcessorUnitTest::kAlphaTextureIdx; 473fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth static const SkShader::TileMode kTileModes[] = { 474fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kClamp_TileMode, 475fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kRepeat_TileMode, 476fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kMirror_TileMode, 477fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth }; 478fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::TileMode tileModes[] = { 479fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 480fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 481fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth }; 482fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode 483fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth : GrTextureParams::kNone_FilterMode); 484fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 485502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth return GrDistanceFieldPathGeoProc::Create(GrRandomColor(random), 4864eaf9cef5a76098f78efac30beb966ac833d32c2joshualitt GrTest::TestMatrix(random), 487502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth textures[texIdx], 488502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth params, 4891ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt random->nextBool() ? kSimilarity_DistanceFieldEffectFlag : 0); 490fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 491fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 492fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 493fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 4949b98932adaceb7ad0a617ade16616923f6bffe84joshualittstruct DistanceFieldLCDBatchTracker { 4959b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGPInput fInputColorType; 4969b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 497290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt bool fUsesLocalCoords; 4989b98932adaceb7ad0a617ade16616923f6bffe84joshualitt}; 4999b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 500502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldLCDTextGeoProc : public GrGLGeometryProcessor { 501609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic: 502502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrGLDistanceFieldLCDTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&) 50321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth : fColor(GrColor_ILLEGAL) { 504502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f); 50521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth } 506609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 50736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 508502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = 509502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth args.fGP.cast<GrDistanceFieldLCDTextGeoProc>(); 5109b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const DistanceFieldLCDBatchTracker& local = args.fBT.cast<DistanceFieldLCDBatchTracker>(); 5119b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGLGPBuilder* pb = args.fPB; 512609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 5132dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); 514abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 515abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 516abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt vsBuilder->emitAttributes(dfTexEffect); 517abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 5189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // setup pass through color 5199b98932adaceb7ad0a617ade16616923f6bffe84joshualitt this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, 5209b98932adaceb7ad0a617ade16616923f6bffe84joshualitt &fColorUniform); 5219b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 522abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 523dd2198701b0ec9da61ecf73418cad03642d715e7joshualitt this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix()); 5244973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 525abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 52646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, 527e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt args.fTransformsIn, args.fTransformsOut); 5285b143038cb47763974d2750ed78d436eb6c38beajvanverth 529bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // set up varyings 530bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); 531bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GrGLVertToFrag recipScale(kFloat_GrSLType); 532bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GrGLVertToFrag st(kVec2f_GrSLType); 533221360a514fb4bfff5b461e83262306b2a0f36afjvanverth args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); 534221360a514fb4bfff5b461e83262306b2a0f36afjvanverth vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); 535bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 536bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GrGLVertToFrag uv(kVec2f_GrSLType); 537bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); 538bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // this is only used with text, so our texture bounds always match the glyph atlas 539bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", " 540bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(), 541bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth dfTexEffect.inTextureCoords()->fName); 542bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 543bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // add frag shader code 54429bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 54530ba436f04e61d4505fb854d5fc56079636e0788joshualitt 54630ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkAssertResult(fsBuilder->enableFeature( 54730ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 54830ba436f04e61d4505fb854d5fc56079636e0788joshualitt 549609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // create LCD offset adjusted by inverse of transform 550fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 551fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, 552fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth pb->ctxInfo().standard())); 5535a105ff05303ac82a867b8b84a1edd145bd46218jvanverth fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 554fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, 555fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth pb->ctxInfo().standard())); 5565a105ff05303ac82a867b8b84a1edd145bd46218jvanverth if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { 5575a105ff05303ac82a867b8b84a1edd145bd46218jvanverth fsBuilder->codeAppend("float delta = -" GR_FONT_ATLAS_LCD_DELTA ";\n"); 5585a105ff05303ac82a867b8b84a1edd145bd46218jvanverth } else { 5595a105ff05303ac82a867b8b84a1edd145bd46218jvanverth fsBuilder->codeAppend("float delta = " GR_FONT_ATLAS_LCD_DELTA ";\n"); 5605a105ff05303ac82a867b8b84a1edd145bd46218jvanverth } 56178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth if (isUniformScale) { 562bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth fsBuilder->codeAppendf("float dy = abs(dFdy(%s.y));", st.fsIn()); 563221360a514fb4bfff5b461e83262306b2a0f36afjvanverth fsBuilder->codeAppend("vec2 offset = vec2(dy*delta, 0.0);"); 564609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } else { 565bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); 566bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 567bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 568bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 569bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppend("vec2 offset = delta*Jdx;"); 570609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 571609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 572609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // green is distance to uv center 57330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tvec4 texColor = "); 574c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType); 57530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 57630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tvec3 distance;\n"); 57730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance.y = texColor.r;\n"); 578609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // red is distance to left offset 57930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n"); 58030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\ttexColor = "); 581c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType); 58230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 58330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance.x = texColor.r;\n"); 584609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // blue is distance to right offset 58530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); 58630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\ttexColor = "); 587c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType); 58830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 58930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); 5902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 59130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance = " 592ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));"); 5932d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 59421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust width based on gamma 59521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth const char* distanceAdjustUniName = NULL; 59621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility, 59721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth kVec3f_GrSLType, kDefault_GrSLPrecision, 59821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "DistanceAdjust", &distanceAdjustUniName); 59921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); 60021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 601609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // To be strictly correct, we should compute the anti-aliasing factor separately 602609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // for each color component. However, this is only important when using perspective 603609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // transformations, and even then using a single factor seems like a reasonable 604609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // trade-off between quality and speed. 605354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("float afwidth;"); 60678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth if (isUniformScale) { 607354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 608354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 609354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 610354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 611609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // this gives us a smooth step across approximately one fragment 612bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*dy;"); 613609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } else { 614354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 615354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 616354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 617354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));"); 618d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 619d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 620d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 621d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 622d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 623d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("} else {"); 624d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 625d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("}"); 626354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 627354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 628609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 629609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // this gives us a smooth step across approximately one fragment 630354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 631609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 632609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 63321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fsBuilder->codeAppend( 63421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);"); 63530ba436f04e61d4505fb854d5fc56079636e0788joshualitt 6362dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 637609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 638609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6397510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen virtual void setData(const GrGLProgramDataManager& pdman, 6409b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const GrPrimitiveProcessor& processor, 64136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const GrBatchTracker& bt) override { 64221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth SkASSERT(fDistanceAdjustUni.isValid()); 643609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 644502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = 645502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth processor.cast<GrDistanceFieldLCDTextGeoProc>(); 646502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dfTexEffect.getDistanceAdjust(); 64721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth if (wa != fDistanceAdjust) { 64821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth pdman.set3f(fDistanceAdjustUni, 64921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fR, 65021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fG, 65121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fB); 65221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjust = wa; 6532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth } 6549b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 655e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt this->setUniformViewMatrix(pdman, dfTexEffect.viewMatrix()); 656ee2af95db72152dfa61c841875df0594ca93437djoshualitt 6579b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>(); 6589b98932adaceb7ad0a617ade16616923f6bffe84joshualitt if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { 6599b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrGLfloat c[4]; 6609b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColorToRGBAFloat(local.fColor, c); 6619b98932adaceb7ad0a617ade16616923f6bffe84joshualitt pdman.set4fv(fColorUniform, 1, c); 6629b98932adaceb7ad0a617ade16616923f6bffe84joshualitt fColor = local.fColor; 6639b98932adaceb7ad0a617ade16616923f6bffe84joshualitt } 664609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 665609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 66646d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 6679b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const GrBatchTracker& bt, 668cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 669b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 670502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>(); 671609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6729b98932adaceb7ad0a617ade16616923f6bffe84joshualitt const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>(); 6738fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 6748fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt key |= local.fInputColorType << 16; 675e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 6768fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 677609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 678609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 679609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate: 68021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth GrColor fColor; 68121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fColorUniform; 682502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust; 68321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fDistanceAdjustUni; 684609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 685249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGLGeometryProcessor INHERITED; 686609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}; 687609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 688609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 689609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 690502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc( 6918059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrColor color, const SkMatrix& viewMatrix, 6922d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth GrTexture* texture, const GrTextureParams& params, 69321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth DistanceAdjust distanceAdjust, 69478f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth uint32_t flags) 695e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 696e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 6972e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 69821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(distanceAdjust) 6992dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt , fFlags(flags & kLCD_DistanceFieldEffectMask){ 70078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag)); 701502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldLCDTextGeoProc>(); 702c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 703c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco kHigh_GrSLPrecision)); 70471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 7055a105ff05303ac82a867b8b84a1edd145bd46218jvanverth kVec2s_GrVertexAttribType)); 706609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org this->addTextureAccess(&fTextureAccess); 707609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 708609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 709502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::getGLProcessorKey(const GrBatchTracker& bt, 710cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps& caps, 711502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrProcessorKeyBuilder* b) const { 712502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, bt, caps, b); 713eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 714eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 715abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualittGrGLPrimitiveProcessor* 716502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::createGLInstance(const GrBatchTracker& bt, 717cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&) const { 718502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth return SkNEW_ARGS(GrGLDistanceFieldLCDTextGeoProc, (*this, bt)); 719609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 720609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 721502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthvoid GrDistanceFieldLCDTextGeoProc::initBatchTracker(GrBatchTracker* bt, 722502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrPipelineInfo& init) const { 7239b98932adaceb7ad0a617ade16616923f6bffe84joshualitt DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>(); 7249b98932adaceb7ad0a617ade16616923f6bffe84joshualitt local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false); 725290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt local->fUsesLocalCoords = init.fUsesLocalCoords; 7269b98932adaceb7ad0a617ade16616923f6bffe84joshualitt} 7279b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 728609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 729609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 730502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc); 731609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 732502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(SkRandom* random, 733b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext*, 734b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 735b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture* textures[]) { 736b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt int texIdx = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 737b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 738609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org static const SkShader::TileMode kTileModes[] = { 739609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kClamp_TileMode, 740609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kRepeat_TileMode, 741609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kMirror_TileMode, 742609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org }; 743609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::TileMode tileModes[] = { 744609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 745609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 746609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org }; 747609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode : 748609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org GrTextureParams::kNone_FilterMode); 74921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; 75078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth uint32_t flags = kUseLCD_DistanceFieldEffectFlag; 75178f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; 75278f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; 753502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(random), 7544eaf9cef5a76098f78efac30beb966ac833d32c2joshualitt GrTest::TestMatrix(random), 755502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth textures[texIdx], params, 756502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth wa, 757502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth flags); 758d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 759