GrDistanceFieldGeoProc.cpp revision 64c4728c70001ed074fecf5c4e083781987b12e9
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 14249af15fb82833d2274850c589812b6e69df0033joshualitt#include "gl/GrGLGeometryProcessor.h" 1564c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h" 162d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 172d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLProgramBuilder.h" 18018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 192d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLVertexShaderBuilder.h" 2064c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLUtil.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 25502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldA8TextGeoProc : public GrGLGeometryProcessor { 26d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.compublic: 27465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldA8TextGeoProc() 285559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt : fViewMatrix(SkMatrix::InvalidMatrix()) 295559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt , fColor(GrColor_ILLEGAL) 309564ce60a657acce89fb956deb8645b324eaad1ejvanverth#ifdef SK_GAMMA_APPLY_TO_A8 3121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(-1.0f) 329564ce60a657acce89fb956deb8645b324eaad1ejvanverth#endif 339564ce60a657acce89fb956deb8645b324eaad1ejvanverth {} 34d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 3536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 36502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = 37502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth args.fGP.cast<GrDistanceFieldA8TextGeoProc>(); 388dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLGPBuilder* pb = args.fPB; 392d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); 4030ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkAssertResult(fsBuilder->enableFeature( 412d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 426c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 432d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); 44abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 45abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 46abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt vsBuilder->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) 522d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel fDistanceAdjustUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibility, 5321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth kFloat_GrSLType, kDefault_GrSLPrecision, 5421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "DistanceAdjust", &distanceAdjustUniName); 5521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif 56d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 579b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // Setup pass through color 58b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (!dfTexEffect.colorIgnored()) { 59b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (dfTexEffect.hasVertexColor()) { 60b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); 61b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } else { 62b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); 63b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 64b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 656c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 66abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 675559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix(), 685559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 694973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 70abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 71f529439fea003851d986a0573a7e0465754b2a48egdaniel this->emitTransforms(pb, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, 72e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt args.fTransformsIn, args.fTransformsOut); 73abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 74bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // add varyings 758dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag recipScale(kFloat_GrSLType); 768dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag st(kVec2f_GrSLType); 77bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag); 78f529439fea003851d986a0573a7e0465754b2a48egdaniel pb->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); 79221360a514fb4bfff5b461e83262306b2a0f36afjvanverth vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); 80bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 81922c8b13c512c3287509936795735c1b31bedba9joshualitt // compute numbers to be hardcoded to convert texture coordinates from int to float 82922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(dfTexEffect.numTextures() == 1); 83922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); 847375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height())); 85922c8b13c512c3287509936795735c1b31bedba9joshualitt SkScalar recipWidth = 1.0f / atlas->width(); 86922c8b13c512c3287509936795735c1b31bedba9joshualitt SkScalar recipHeight = 1.0f / atlas->height(); 87922c8b13c512c3287509936795735c1b31bedba9joshualitt 888dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag uv(kVec2f_GrSLType); 89f529439fea003851d986a0573a7e0465754b2a48egdaniel pb->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); 90922c8b13c512c3287509936795735c1b31bedba9joshualitt vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(), 917375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth, 927375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight, 93bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth dfTexEffect.inTextureCoords()->fName); 94bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 95fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 960d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), 970d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel kHigh_GrSLPrecision)); 985a105ff05303ac82a867b8b84a1edd145bd46218jvanverth fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 99fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth 100fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend("\tfloat texColor = "); 101c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], 102fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth "uv", 103d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com kVec2f_GrSLType); 104fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(".r;\n"); 10530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tfloat distance = " 106fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 10721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 10821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust width based on gamma 10921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); 11021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth#endif 1116c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 112354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("float afwidth;"); 113bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth if (isSimilarity) { 114354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 115354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 116221360a514fb4bfff5b461e83262306b2a0f36afjvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 117354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 1184362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org // this gives us a smooth step across approximately one fragment 119221360a514fb4bfff5b461e83262306b2a0f36afjvanverth // we use y to work around a Mali400 bug in the x direction 120221360a514fb4bfff5b461e83262306b2a0f36afjvanverth fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));", 121bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth st.fsIn()); 1224362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } else { 123354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 124354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 125354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 126354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));"); 127d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 128d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 129d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 130d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 131d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 132d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("} else {"); 133d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 134d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("}"); 135d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth 136bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppendf("vec2 Jdx = dFdx(%s);", st.fsIn()); 137bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppendf("vec2 Jdy = dFdy(%s);", st.fsIn()); 138354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 139354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 1404362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org 1414362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org // this gives us a smooth step across approximately one fragment 142354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 1434362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } 144354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); 1454d517fdbb145cb95e5e935470df331e1b6667cfcjvanverth 1462dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 147d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com } 148d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 149018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc) override { 1502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 151502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>(); 15221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float distanceAdjust = dfTexEffect.getDistanceAdjust(); 15321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth if (distanceAdjust != fDistanceAdjust) { 15421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth pdman.set1f(fDistanceAdjustUni, distanceAdjust); 15521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjust = distanceAdjust; 1562d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth } 1572d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 158e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt const GrDistanceFieldA8TextGeoProc& dfa8gp = proc.cast<GrDistanceFieldA8TextGeoProc>(); 1595559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt 1605559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (!dfa8gp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfa8gp.viewMatrix())) { 1615559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fViewMatrix = dfa8gp.viewMatrix(); 162018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 16364c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 1645559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 1655559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 166ee2af95db72152dfa61c841875df0594ca93437djoshualitt 167b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (dfa8gp.color() != fColor && !dfa8gp.hasVertexColor()) { 168018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float c[4]; 169b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt GrColorToRGBAFloat(dfa8gp.color(), c); 1709b98932adaceb7ad0a617ade16616923f6bffe84joshualitt pdman.set4fv(fColorUniform, 1, c); 171b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt fColor = dfa8gp.color(); 1729b98932adaceb7ad0a617ade16616923f6bffe84joshualitt } 1736c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org } 174d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 17546d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 176cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 177b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 178502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>(); 1798fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 180b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.hasVertexColor() << 16; 181b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.colorIgnored() << 17; 182e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 1838fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 184922c8b13c512c3287509936795735c1b31bedba9joshualitt 185922c8b13c512c3287509936795735c1b31bedba9joshualitt // Currently we hardcode numbers to convert atlas coordinates to normalized floating point 186922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(gp.numTextures() == 1); 187922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = gp.textureAccess(0).getTexture(); 188922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(atlas); 189922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->width()); 190922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->height()); 1914362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org } 1924362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org 193d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.comprivate: 1945559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 1959b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 1969b98932adaceb7ad0a617ade16616923f6bffe84joshualitt UniformHandle fColorUniform; 1975559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 19850282b4390dcddcf3b1d51631c0133045ae1f233mtklein#ifdef SK_GAMMA_APPLY_TO_A8 19921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float fDistanceAdjust; 20021deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fDistanceAdjustUni; 20150282b4390dcddcf3b1d51631c0133045ae1f233mtklein#endif 2026c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org 203249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGLGeometryProcessor INHERITED; 204d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com}; 205d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 206d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 207d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 208502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color, 2098059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 2102e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrTexture* texture, 2116c89c34614573797ce63e429229b6f7848df0bb7commit-bot@chromium.org const GrTextureParams& params, 2122d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 21321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth float distanceAdjust, 2142d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 215b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt uint32_t flags, 216b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt bool usesLocalCoords) 217e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 218e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 2192e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 2202d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 22121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(distanceAdjust) 2222d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 223249af15fb82833d2274850c589812b6e69df0033joshualitt , fFlags(flags & kNonLCD_DistanceFieldEffectMask) 22496fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fInColor(nullptr) 225b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fUsesLocalCoords(usesLocalCoords) { 22678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); 227502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldA8TextGeoProc>(); 228f2539d50f911914af0f80f0092ff8c654869e650senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 229f2539d50f911914af0f80f0092ff8c654869e650senorblanco kHigh_GrSLPrecision)); 2302dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt if (flags & kColorAttr_DistanceFieldEffectFlag) { 23171c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 2322dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt } 23371c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 2345a105ff05303ac82a867b8b84a1edd145bd46218jvanverth kVec2s_GrVertexAttribType)); 235d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com this->addTextureAccess(&fTextureAccess); 236d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 237d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 238465283cdf98ed9ab5285ca7b9814e430fca1d452joshualittvoid GrDistanceFieldA8TextGeoProc::getGLProcessorKey(const GrGLSLCaps& caps, 239eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrProcessorKeyBuilder* b) const { 240465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldA8TextGeoProc::GenKey(*this, caps, b); 241eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 242eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 243465283cdf98ed9ab5285ca7b9814e430fca1d452joshualittGrGLPrimitiveProcessor* GrDistanceFieldA8TextGeoProc::createGLInstance(const GrGLSLCaps&) const { 244465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt return new GrGLDistanceFieldA8TextGeoProc(); 245d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 246d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 247d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 248d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 249502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldA8TextGeoProc); 250d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 251c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrGeometryProcessor* GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorTestData* d) { 2520067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 2530067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 254d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com static const SkShader::TileMode kTileModes[] = { 255d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kClamp_TileMode, 256d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kRepeat_TileMode, 257d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::kMirror_TileMode, 258d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com }; 259d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com SkShader::TileMode tileModes[] = { 2600067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 2610067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 262d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com }; 2630067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode : 264d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com GrTextureParams::kNone_FilterMode); 265d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 2660067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrDistanceFieldA8TextGeoProc::Create(GrRandomColor(d->fRandom), 2670067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTest::TestMatrix(d->fRandom), 2680067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fTextures[texIdx], params, 2692d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#ifdef SK_GAMMA_APPLY_TO_A8 2700067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextF(), 2712d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth#endif 2720067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool() ? 273b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kSimilarity_DistanceFieldEffectFlag : 0, 2740067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool()); 275609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 276609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 277609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 278609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 279502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldPathGeoProc : public GrGLGeometryProcessor { 280fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthpublic: 281465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldPathGeoProc() 2825559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt : fViewMatrix(SkMatrix::InvalidMatrix()) 2835559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt , fColor(GrColor_ILLEGAL) 2845559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt , fTextureSize(SkISize::Make(-1, -1)) {} 285fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 28636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 287502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>(); 288fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 2898dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLGPBuilder* pb = args.fPB; 2902d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); 291fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkAssertResult(fsBuilder->enableFeature( 2922d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 293fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 2942d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); 295abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 296abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 297abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt vsBuilder->emitAttributes(dfTexEffect); 298abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 2998dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag v(kVec2f_GrSLType); 300f529439fea003851d986a0573a7e0465754b2a48egdaniel pb->addVarying("TextureCoords", &v, kHigh_GrSLPrecision); 301fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3029b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // setup pass through color 303b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (!dfTexEffect.colorIgnored()) { 304b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (dfTexEffect.hasVertexColor()) { 305b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor); 306b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } else { 307b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); 308b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 309b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 310e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName); 311e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed 312abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 3135559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix(), 3145559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 315abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 316abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 317f529439fea003851d986a0573a7e0465754b2a48egdaniel this->emitTransforms(pb, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, 318e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt args.fTransformsIn, args.fTransformsOut); 3194973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 32096fcdcc219d2a0d3579719b84b28bede76efba64halcanary const char* textureSizeUniName = nullptr; 3212d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel fTextureSizeUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibility, 322f529439fea003851d986a0573a7e0465754b2a48egdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 323f529439fea003851d986a0573a7e0465754b2a48egdaniel "TextureSize", &textureSizeUniName); 324e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed 325fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 3260d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), 3270d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel kHigh_GrSLPrecision)); 328e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); 329fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth 330fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend("float texColor = "); 331c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], 332fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth "uv", 333fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth kVec2f_GrSLType); 334fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth fsBuilder->codeAppend(".r;"); 335fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("float distance = " 336fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 337fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3380d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), 3390d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel kHigh_GrSLPrecision)); 340e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); 341fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("float afwidth;"); 342fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { 343354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 344354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 345354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 346354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 347fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth // this gives us a smooth step across approximately one fragment 348bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(st.y));"); 349fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } else { 350354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 351354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 352354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 353354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));"); 354d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 355d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 356d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 357d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 358d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 359d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("} else {"); 360d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 361d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("}"); 362d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth 363354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 364354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 365354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 366354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 367fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 368fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth // this gives us a smooth step across approximately one fragment 369fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 370fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 371fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); 372fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 3732dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 374fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 375fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 376018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc) override { 377e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkASSERT(fTextureSizeUni.isValid()); 378fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 37987f48d997ec29e5eeaa7567355775e93465dd60djoshualitt GrTexture* texture = proc.texture(0); 380fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth if (texture->width() != fTextureSize.width() || 381fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth texture->height() != fTextureSize.height()) { 382fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth fTextureSize = SkISize::Make(texture->width(), texture->height()); 383e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed pdman.set2f(fTextureSizeUni, 384e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkIntToScalar(fTextureSize.width()), 385e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed SkIntToScalar(fTextureSize.height())); 386fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 3879b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 388e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>(); 3895559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt 3905559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (!dfpgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfpgp.viewMatrix())) { 3915559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fViewMatrix = dfpgp.viewMatrix(); 392018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 39364c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 3945559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 3955559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 396ee2af95db72152dfa61c841875df0594ca93437djoshualitt 397b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (dfpgp.color() != fColor) { 398018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float c[4]; 399b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt GrColorToRGBAFloat(dfpgp.color(), c); 4009b98932adaceb7ad0a617ade16616923f6bffe84joshualitt pdman.set4fv(fColorUniform, 1, c); 401b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt fColor = dfpgp.color(); 4029b98932adaceb7ad0a617ade16616923f6bffe84joshualitt } 403fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 404fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 40546d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 406cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 407fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth GrProcessorKeyBuilder* b) { 408502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>(); 409fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 4108fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 411b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.colorIgnored() << 16; 412b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.hasVertexColor() << 17; 413e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 4148fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 415fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth } 416fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 417fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverthprivate: 4189b98932adaceb7ad0a617ade16616923f6bffe84joshualitt UniformHandle fColorUniform; 419e4ef1ca5be11aed67c0ed0c7eb1862696fb063e3reed UniformHandle fTextureSizeUni; 4205559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 4215559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 4229b98932adaceb7ad0a617ade16616923f6bffe84joshualitt GrColor fColor; 4239b98932adaceb7ad0a617ade16616923f6bffe84joshualitt SkISize fTextureSize; 424fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 425fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth typedef GrGLGeometryProcessor INHERITED; 426fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth}; 427fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 428fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 429fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 430502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc( 4312e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrColor color, 4328059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 4332e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt GrTexture* texture, 4342e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt const GrTextureParams& params, 435b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt uint32_t flags, 436b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt bool usesLocalCoords) 437e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 438e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 4392e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 440fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth , fFlags(flags & kNonLCD_DistanceFieldEffectMask) 44196fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fInColor(nullptr) 442b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fUsesLocalCoords(usesLocalCoords) { 443fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask)); 444502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldPathGeoProc>(); 445f2539d50f911914af0f80f0092ff8c654869e650senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 446f2539d50f911914af0f80f0092ff8c654869e650senorblanco kHigh_GrSLPrecision)); 4472dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt if (flags & kColorAttr_DistanceFieldEffectFlag) { 44871c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType)); 4492dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt } 45071c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 451b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kVec2f_GrVertexAttribType)); 452fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth this->addTextureAccess(&fTextureAccess); 453fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 454fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 455465283cdf98ed9ab5285ca7b9814e430fca1d452joshualittvoid GrDistanceFieldPathGeoProc::getGLProcessorKey(const GrGLSLCaps& caps, 456502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrProcessorKeyBuilder* b) const { 457465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldPathGeoProc::GenKey(*this, caps, b); 458eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 459eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 460465283cdf98ed9ab5285ca7b9814e430fca1d452joshualittGrGLPrimitiveProcessor* GrDistanceFieldPathGeoProc::createGLInstance(const GrGLSLCaps&) const { 461465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt return new GrGLDistanceFieldPathGeoProc(); 462fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 463fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 464fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 465fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 466502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc); 467fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 468c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData* d) { 4690067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx 4700067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt : GrProcessorUnitTest::kAlphaTextureIdx; 471fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth static const SkShader::TileMode kTileModes[] = { 472fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kClamp_TileMode, 473fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kRepeat_TileMode, 474fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::kMirror_TileMode, 475fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth }; 476fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth SkShader::TileMode tileModes[] = { 4770067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 4780067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 479fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth }; 4800067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode 4810067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt : GrTextureParams::kNone_FilterMode); 482fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 4830067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrDistanceFieldPathGeoProc::Create(GrRandomColor(d->fRandom), 4840067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTest::TestMatrix(d->fRandom), 4850067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fTextures[texIdx], 486502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth params, 4870067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool() ? 488b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kSimilarity_DistanceFieldEffectFlag : 0, 4890067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool()); 490fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth} 491fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 492fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth/////////////////////////////////////////////////////////////////////////////// 493fa38a30897ceda3e93355d69b8a6812c823f41f6jvanverth 494502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthclass GrGLDistanceFieldLCDTextGeoProc : public GrGLGeometryProcessor { 495609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgpublic: 496465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldLCDTextGeoProc() 4975559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL) { 498502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f); 49921deace8efc8e167d8626187ef0e6b4c241324b6jvanverth } 500609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 50136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 502502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = 503502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth args.fGP.cast<GrDistanceFieldLCDTextGeoProc>(); 5048dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLGPBuilder* pb = args.fPB; 505609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 5062d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder(); 507abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 508abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 509abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt vsBuilder->emitAttributes(dfTexEffect); 510abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 5119b98932adaceb7ad0a617ade16616923f6bffe84joshualitt // setup pass through color 512b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt if (!dfTexEffect.colorIgnored()) { 513b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt this->setupUniformColor(pb, args.fOutputColor, &fColorUniform); 514b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt } 5159b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 516abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 5175559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix(), 5185559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 5194973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 520abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 521f529439fea003851d986a0573a7e0465754b2a48egdaniel this->emitTransforms(pb, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName, 522e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt args.fTransformsIn, args.fTransformsOut); 5235b143038cb47763974d2750ed78d436eb6c38beajvanverth 524bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // set up varyings 525bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask); 5268dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag recipScale(kFloat_GrSLType); 5278dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag st(kVec2f_GrSLType); 528f529439fea003851d986a0573a7e0465754b2a48egdaniel pb->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision); 529221360a514fb4bfff5b461e83262306b2a0f36afjvanverth vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName); 530bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 531922c8b13c512c3287509936795735c1b31bedba9joshualitt // compute numbers to be hardcoded to convert texture coordinates from int to float 532922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(dfTexEffect.numTextures() == 1); 533922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture(); 5347375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height())); 535922c8b13c512c3287509936795735c1b31bedba9joshualitt SkScalar recipWidth = 1.0f / atlas->width(); 536922c8b13c512c3287509936795735c1b31bedba9joshualitt SkScalar recipHeight = 1.0f / atlas->height(); 537922c8b13c512c3287509936795735c1b31bedba9joshualitt 5388dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag uv(kVec2f_GrSLType); 539f529439fea003851d986a0573a7e0465754b2a48egdaniel pb->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision); 540922c8b13c512c3287509936795735c1b31bedba9joshualitt vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(), 5417375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth, 5427375d6bab2ee8b02da276597ed4d60f22f54eb89joshualitt GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight, 543bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth dfTexEffect.inTextureCoords()->fName); 544bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 545bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth // add frag shader code 5462d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder(); 54730ba436f04e61d4505fb854d5fc56079636e0788joshualitt 54830ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkAssertResult(fsBuilder->enableFeature( 5492d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); 55030ba436f04e61d4505fb854d5fc56079636e0788joshualitt 551609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // create LCD offset adjusted by inverse of transform 552fdf7ccc2012dd06305cc3a0fbc788a483fce7b6ajvanverth // Use highp to work around aliasing issues 5530d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), 5540d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel kHigh_GrSLPrecision)); 5555a105ff05303ac82a867b8b84a1edd145bd46218jvanverth fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 5560d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel fsBuilder->codeAppend(GrGLSLShaderVar::PrecisionString(pb->glslCaps(), 5570d3f061262a53b775f0a92b0abf8a4a846290d65egdaniel kHigh_GrSLPrecision)); 558922c8b13c512c3287509936795735c1b31bedba9joshualitt 559922c8b13c512c3287509936795735c1b31bedba9joshualitt SkScalar lcdDelta = 1.0f / (3.0f * atlas->width()); 5605a105ff05303ac82a867b8b84a1edd145bd46218jvanverth if (dfTexEffect.getFlags() & kBGR_DistanceFieldEffectFlag) { 561922c8b13c512c3287509936795735c1b31bedba9joshualitt fsBuilder->codeAppendf("float delta = -%.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta); 5625a105ff05303ac82a867b8b84a1edd145bd46218jvanverth } else { 563922c8b13c512c3287509936795735c1b31bedba9joshualitt fsBuilder->codeAppendf("float delta = %.*f;\n", SK_FLT_DECIMAL_DIG, lcdDelta); 5645a105ff05303ac82a867b8b84a1edd145bd46218jvanverth } 56578f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth if (isUniformScale) { 566bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth fsBuilder->codeAppendf("float dy = abs(dFdy(%s.y));", st.fsIn()); 567221360a514fb4bfff5b461e83262306b2a0f36afjvanverth fsBuilder->codeAppend("vec2 offset = vec2(dy*delta, 0.0);"); 568609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } else { 569bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); 570bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth 571bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 572bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 573bb4a1cf0e66c98c723f04f473a3221b2a4d8ece1jvanverth fsBuilder->codeAppend("vec2 offset = delta*Jdx;"); 574609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 575609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 576609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // green is distance to uv center 57730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tvec4 texColor = "); 578c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], "uv", kVec2f_GrSLType); 57930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 58030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tvec3 distance;\n"); 58130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance.y = texColor.r;\n"); 582609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // red is distance to left offset 58330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tvec2 uv_adjusted = uv - offset;\n"); 58430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\ttexColor = "); 585c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType); 58630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 58730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance.x = texColor.r;\n"); 588609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // blue is distance to right offset 58930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); 59030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\ttexColor = "); 591c369e7c9992a86151a3ea0516ce5308c211b196bjoshualitt fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_GrSLType); 59230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 59330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); 5942d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 59530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\tdistance = " 596ada68ef2dc986478288a8b8ad867fd3aca431162jvanverth "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));"); 5972d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth 59821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth // adjust width based on gamma 59996fcdcc219d2a0d3579719b84b28bede76efba64halcanary const char* distanceAdjustUniName = nullptr; 6002d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel fDistanceAdjustUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibility, 60121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth kVec3f_GrSLType, kDefault_GrSLPrecision, 60221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "DistanceAdjust", &distanceAdjustUniName); 60321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName); 60421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth 605609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // To be strictly correct, we should compute the anti-aliasing factor separately 606609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // for each color component. However, this is only important when using perspective 607609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // transformations, and even then using a single factor seems like a reasonable 608609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // trade-off between quality and speed. 609354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("float afwidth;"); 61078f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth if (isUniformScale) { 611354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For uniform scale, we adjust for the effect of the transformation on the distance 612354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // by using the length of the gradient of the texture coordinates. We use st coordinates 613354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // to ensure we're mapping 1:1 from texel space to pixel space. 614354eba5cb61801130a84378356434d3cc0a4b71ajvanverth 615609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // this gives us a smooth step across approximately one fragment 616bc0273524b039c45dcea2c1ab5ab379c75486c07jvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*dy;"); 617609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } else { 618354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // For general transforms, to determine the amount of correction we multiply a unit 619354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // vector pointing along the SDF gradient direction by the Jacobian of the st coords 620354eba5cb61801130a84378356434d3cc0a4b71ajvanverth // (which is the inverse transform for this fragment) and take the length of the result. 621354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(distance.r));"); 622d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // the length of the gradient may be 0, so we need to check for this 623d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth // this also compensates for the Adreno, which likes to drop tiles on division by 0 624d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);"); 625d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); 626d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); 627d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("} else {"); 628d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); 629d68a550ec890c3e3135ffa119621e17e55d58dd6jvanverth fsBuilder->codeAppend("}"); 630354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); 631354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); 632609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 633609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org // this gives us a smooth step across approximately one fragment 634354eba5cb61801130a84378356434d3cc0a4b71ajvanverth fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); 635609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 636609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 63721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fsBuilder->codeAppend( 63821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth "vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);"); 63927b6335c71bccb96206ff0495793433bfa982777egdaniel // set alpha to be max of rgb coverage 64027b6335c71bccb96206ff0495793433bfa982777egdaniel fsBuilder->codeAppend("val.a = max(max(val.r, val.g), val.b);"); 64130ba436f04e61d4505fb854d5fc56079636e0788joshualitt 64227b6335c71bccb96206ff0495793433bfa982777egdaniel fsBuilder->codeAppendf("%s = val;", args.fOutputCoverage); 643609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 644609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 645018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void setData(const GrGLSLProgramDataManager& pdman, 646465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt const GrPrimitiveProcessor& processor) override { 64721deace8efc8e167d8626187ef0e6b4c241324b6jvanverth SkASSERT(fDistanceAdjustUni.isValid()); 648609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6495559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt const GrDistanceFieldLCDTextGeoProc& dflcd = processor.cast<GrDistanceFieldLCDTextGeoProc>(); 6505559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt GrDistanceFieldLCDTextGeoProc::DistanceAdjust wa = dflcd.getDistanceAdjust(); 65121deace8efc8e167d8626187ef0e6b4c241324b6jvanverth if (wa != fDistanceAdjust) { 65221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth pdman.set3f(fDistanceAdjustUni, 65321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fR, 65421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fG, 65521deace8efc8e167d8626187ef0e6b4c241324b6jvanverth wa.fB); 65621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth fDistanceAdjust = wa; 6572d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth } 6589b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 6595559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (!dflcd.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dflcd.viewMatrix())) { 6605559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fViewMatrix = dflcd.viewMatrix(); 661018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 66264c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 6635559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 6645559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 665ee2af95db72152dfa61c841875df0594ca93437djoshualitt 6665559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt if (dflcd.color() != fColor) { 667018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float c[4]; 6685559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt GrColorToRGBAFloat(dflcd.color(), c); 6699b98932adaceb7ad0a617ade16616923f6bffe84joshualitt pdman.set4fv(fColorUniform, 1, c); 6705559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt fColor = dflcd.color(); 6719b98932adaceb7ad0a617ade16616923f6bffe84joshualitt } 672609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 673609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 67446d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static inline void GenKey(const GrGeometryProcessor& gp, 675cfc18867d982119d9dc2888bf09f1093012daaddjvanverth const GrGLSLCaps&, 676b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 677502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>(); 678609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 6798fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt uint32_t key = dfTexEffect.getFlags(); 680b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt key |= dfTexEffect.colorIgnored() << 16; 681e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt key |= ComputePosKey(dfTexEffect.viewMatrix()) << 25; 6828fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt b->add32(key); 683922c8b13c512c3287509936795735c1b31bedba9joshualitt 684922c8b13c512c3287509936795735c1b31bedba9joshualitt // Currently we hardcode numbers to convert atlas coordinates to normalized floating point 685922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(gp.numTextures() == 1); 686922c8b13c512c3287509936795735c1b31bedba9joshualitt GrTexture* atlas = gp.textureAccess(0).getTexture(); 687922c8b13c512c3287509936795735c1b31bedba9joshualitt SkASSERT(atlas); 688922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->width()); 689922c8b13c512c3287509936795735c1b31bedba9joshualitt b->add32(atlas->height()); 690609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org } 691609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 692609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.orgprivate: 6935559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 69421deace8efc8e167d8626187ef0e6b4c241324b6jvanverth GrColor fColor; 6955559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 69621deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fColorUniform; 697502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrDistanceFieldLCDTextGeoProc::DistanceAdjust fDistanceAdjust; 69821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth UniformHandle fDistanceAdjustUni; 699609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 700249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGLGeometryProcessor INHERITED; 701609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org}; 702609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 703609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 704609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 705502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc( 7068059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrColor color, const SkMatrix& viewMatrix, 7072d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth GrTexture* texture, const GrTextureParams& params, 70821deace8efc8e167d8626187ef0e6b4c241324b6jvanverth DistanceAdjust distanceAdjust, 709b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt uint32_t flags, bool usesLocalCoords) 710e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt : fColor(color) 711e578a95d3ab16544794b94da4e7ae13fc2ce6244joshualitt , fViewMatrix(viewMatrix) 7122e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt , fTextureAccess(texture, params) 71321deace8efc8e167d8626187ef0e6b4c241324b6jvanverth , fDistanceAdjust(distanceAdjust) 714b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fFlags(flags & kLCD_DistanceFieldEffectMask) 715b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt , fUsesLocalCoords(usesLocalCoords) { 71678f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag)); 717502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth this->initClassID<GrDistanceFieldLCDTextGeoProc>(); 718f2539d50f911914af0f80f0092ff8c654869e650senorblanco fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType, 719f2539d50f911914af0f80f0092ff8c654869e650senorblanco kHigh_GrSLPrecision)); 72071c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords", 721b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt kVec2s_GrVertexAttribType)); 722609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org this->addTextureAccess(&fTextureAccess); 723609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 724609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 725465283cdf98ed9ab5285ca7b9814e430fca1d452joshualittvoid GrDistanceFieldLCDTextGeoProc::getGLProcessorKey(const GrGLSLCaps& caps, 726502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth GrProcessorKeyBuilder* b) const { 727465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt GrGLDistanceFieldLCDTextGeoProc::GenKey(*this, caps, b); 728eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 729eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 730465283cdf98ed9ab5285ca7b9814e430fca1d452joshualittGrGLPrimitiveProcessor* GrDistanceFieldLCDTextGeoProc::createGLInstance(const GrGLSLCaps&) const { 731465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt return new GrGLDistanceFieldLCDTextGeoProc(); 732609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org} 733609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 734609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 735609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 736502286d7b8ecf26a3a33e8098335034e21e4b082jvanverthGR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc); 737609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org 738c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrGeometryProcessor* GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessorTestData* d) { 7390067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 7400067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrProcessorUnitTest::kAlphaTextureIdx; 741609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org static const SkShader::TileMode kTileModes[] = { 742609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kClamp_TileMode, 743609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kRepeat_TileMode, 744609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::kMirror_TileMode, 745609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org }; 746609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org SkShader::TileMode tileModes[] = { 7470067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 7480067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt kTileModes[d->fRandom->nextULessThan(SK_ARRAY_COUNT(kTileModes))], 749609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org }; 7500067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTextureParams params(tileModes, d->fRandom->nextBool() ? GrTextureParams::kBilerp_FilterMode : 751609ced42e7cebef533cf9c1622280f5cdda1faaecommit-bot@chromium.org GrTextureParams::kNone_FilterMode); 75221deace8efc8e167d8626187ef0e6b4c241324b6jvanverth DistanceAdjust wa = { 0.0f, 0.1f, -0.1f }; 75378f0718f4dac8bdcc0df43a3280cf8a89d8cf87ajvanverth uint32_t flags = kUseLCD_DistanceFieldEffectFlag; 7540067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt flags |= d->fRandom->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; 7550067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; 7560067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt return GrDistanceFieldLCDTextGeoProc::Create(GrRandomColor(d->fRandom), 7570067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTest::TestMatrix(d->fRandom), 7580067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fTextures[texIdx], params, 759502286d7b8ecf26a3a33e8098335034e21e4b082jvanverth wa, 760b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt flags, 7610067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt d->fRandom->nextBool()); 762d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com} 763