181312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org/* 281312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org * Copyright 2013 Google Inc. 381312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org * 481312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be 581312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org * found in the LICENSE file. 681312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org */ 781312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org 8289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon#include "GrOvalOpFactory.h" 981312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org 105ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h" 11eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrGeometryProcessor.h" 12742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h" 1376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt#include "GrProcessor.h" 14ed0bcad9c8147fd37c23bdda00ec27ec9ef8d66bbsalomon#include "GrResourceProvider.h" 1594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "GrShaderCaps.h" 164f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon#include "GrStyle.h" 17f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org#include "SkRRect.h" 1881312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org#include "SkStrokeRec.h" 192d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 20e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h" 21018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 227ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 2364c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLUtil.h" 24dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "glsl/GrGLSLVarying.h" 25dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "glsl/GrGLSLVertexShaderBuilder.h" 26895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h" 27234d4fba75aac009e34c088037fcd9e244798c40commit-bot@chromium.org 2825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon// TODO(joshualitt) - Break this file up during GrOp post implementation cleanup 2976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 3081312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.orgnamespace { 31bb2ff94e223014403f775c3532a25cc25b00c949brianosman 3281312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.orgstruct EllipseVertex { 33289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fPos; 34289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrColor fColor; 35289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fOffset; 36289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fOuterRadii; 37289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fInnerRadii; 38f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org}; 39f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 405242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.orgstruct DIEllipseVertex { 41289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fPos; 42289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrColor fColor; 43289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fOuterOffset; 44289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fInnerOffset; 455242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org}; 465242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 47289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonstatic inline bool circle_stays_circle(const SkMatrix& m) { return m.isSimilarity(); } 4881312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org} 4981312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org 5090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 5190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 5290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/** 53ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * The output of this effect is a modulation of the input color and coverage for a circle. It 54ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * operates in a space normalized by the circle radius (outer radius in the case of a stroke) 55cdaa97bf664e0d584187efc125bfff670a064a9absalomon * with origin at the circle center. Three vertex attributes are used: 56ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * vec2f : position in device space of the bounding geometry vertices 57cdaa97bf664e0d584187efc125bfff670a064a9absalomon * vec4ub: color 58ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * vec4f : (p.xy, outerRad, innerRad) 59ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * p is the position in the normalized space. 60ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * outerRad is the outerRadius in device space. 61ce1c8869cf5e37753f9c8193314d93bff897d014bsalomon * innerRad is the innerRadius in normalized space (ignored if not stroking). 62fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein * If fUsesDistanceVectorField is set in fragment processors in the same program, then 636c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth * an additional vertex attribute is available via args.fFragBuilder->distanceVectorName(): 646c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth * vec4f : (v.xy, outerDistance, innerDistance) 656c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth * v is a normalized vector pointing to the outer edge 666c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth * outerDistance is the distance to the outer edge, < 0 if we are outside of the shape 676c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth * if stroking, innerDistance is the distance to the inner edge, < 0 if outside 684f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon * Additional clip planes are supported for rendering circular arcs. The additional planes are 694f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon * either intersected or unioned together. Up to three planes are supported (an initial plane, 704f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon * a plane intersected with the initial plane, and a plane unioned with the first two). Only two 7153e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * are useful for any given arc, but having all three in one instance allows combining different 724f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon * types of arcs. 7390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 7490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 75cdaa97bf664e0d584187efc125bfff670a064a9absalomonclass CircleGeometryProcessor : public GrGeometryProcessor { 7690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 774f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon CircleGeometryProcessor(bool stroke, bool clipPlane, bool isectPlane, bool unionPlane, 784f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon const SkMatrix& localMatrix) 794f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon : fLocalMatrix(localMatrix) { 80cdaa97bf664e0d584187efc125bfff670a064a9absalomon this->initClassID<CircleGeometryProcessor>(); 816cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType, 826cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon kHigh_GrSLPrecision); 836cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 846750e91544b98b839c3148baef996ab2860233a4Jim Van Verth fInCircleEdge = &this->addVertexAttrib("inCircleEdge", kVec4f_GrVertexAttribType, 856750e91544b98b839c3148baef996ab2860233a4Jim Van Verth kHigh_GrSLPrecision); 864f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (clipPlane) { 874f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fInClipPlane = &this->addVertexAttrib("inClipPlane", kVec3f_GrVertexAttribType); 884f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 894f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fInClipPlane = nullptr; 904f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 914f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (isectPlane) { 924f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fInIsectPlane = &this->addVertexAttrib("inIsectPlane", kVec3f_GrVertexAttribType); 934f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 944f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fInIsectPlane = nullptr; 954f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 964f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (unionPlane) { 974f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fInUnionPlane = &this->addVertexAttrib("inUnionPlane", kVec3f_GrVertexAttribType); 984f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 994f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fInUnionPlane = nullptr; 1004f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 101cdaa97bf664e0d584187efc125bfff670a064a9absalomon fStroke = stroke; 10290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 10390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 104fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein bool implementsDistanceVector() const override { return !fInClipPlane; } 10568f2f7dc4229c3761dd5074a94c35878abcb9a36dvonbeck 106d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon ~CircleGeometryProcessor() override {} 10790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 10836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "CircleEdge"; } 10990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 11094efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 11131df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon GLSLProcessor::GenKey(*this, caps, b); 11231df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon } 11331df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon 11494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 11531df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon return new GLSLProcessor(); 11631df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon } 11731df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon 11831df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomonprivate: 11957d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel class GLSLProcessor : public GrGLSLGeometryProcessor { 12090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 121bb2ff94e223014403f775c3532a25cc25b00c949brianosman GLSLProcessor() {} 12290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 123289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 124cdaa97bf664e0d584187efc125bfff670a064a9absalomon const CircleGeometryProcessor& cgp = args.fGP.cast<CircleGeometryProcessor>(); 1254ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 1260eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 1277ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 1284f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 1292dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 130abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 131cdaa97bf664e0d584187efc125bfff670a064a9absalomon varyingHandler->emitAttributes(cgp); 1326750e91544b98b839c3148baef996ab2860233a4Jim Van Verth fragBuilder->codeAppend("highp vec4 circleEdge;"); 1336750e91544b98b839c3148baef996ab2860233a4Jim Van Verth varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEdge", 1346750e91544b98b839c3148baef996ab2860233a4Jim Van Verth kHigh_GrSLPrecision); 1354f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (cgp.fInClipPlane) { 1364f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fragBuilder->codeAppend("vec3 clipPlane;"); 1374f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipPlane"); 1384f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 1394f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (cgp.fInIsectPlane) { 1404f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkASSERT(cgp.fInClipPlane); 1414f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fragBuilder->codeAppend("vec3 isectPlane;"); 1424f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isectPlane"); 1434f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 1444f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (cgp.fInUnionPlane) { 1454f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkASSERT(cgp.fInClipPlane); 1464f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fragBuilder->codeAppend("vec3 unionPlane;"); 1474f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unionPlane"); 1484f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 149abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 150b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt // setup pass through color 15131df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon varyingHandler->addPassThroughAttribute(cgp.fInColor, args.fOutputColor); 1529b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 153abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 15431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon this->setupPosition(vertBuilder, gpArgs, cgp.fInPosition->fName); 155abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 156abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 1577ea439b2203855db97330b25945b87dd4b170b8begdaniel this->emitTransforms(vertBuilder, 1580eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler, 1597ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 1604ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs->fPositionVar, 16131df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon cgp.fInPosition->fName, 16231df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon cgp.fLocalMatrix, 163a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon args.fFPCoordTransformHandler); 1644ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1656750e91544b98b839c3148baef996ab2860233a4Jim Van Verth fragBuilder->codeAppend("highp float d = length(circleEdge.xy);"); 1664f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fragBuilder->codeAppend("float distanceToOuterEdge = circleEdge.z * (1.0 - d);"); 1674f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fragBuilder->codeAppend("float edgeAlpha = clamp(distanceToOuterEdge, 0.0, 1.0);"); 168cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (cgp.fStroke) { 169289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppend( 170289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "float distanceToInnerEdge = circleEdge.z * (d - circleEdge.w);"); 1716c177a1a49fcfe8bfd5f3ffda3ee50bbe2679463jvanverth fragBuilder->codeAppend("float innerAlpha = clamp(distanceToInnerEdge, 0.0, 1.0);"); 1724ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); 17390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 1740a6cb602e5866f7a8cd1630d0c907749f5182837commit-bot@chromium.org 17568f2f7dc4229c3761dd5074a94c35878abcb9a36dvonbeck if (args.fDistanceVectorName) { 176adf4edc4d6ddf781b2910f457ba360d99072604absalomon const char* innerEdgeDistance = cgp.fStroke ? "distanceToInnerEdge" : "0.0"; 177289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppendf( 178289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "if (d == 0.0) {" // if on the center of the circle 179289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon " %s = vec4(1.0, 0.0, distanceToOuterEdge, " 180289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon " %s);", // no normalize 181289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon args.fDistanceVectorName, 182289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon innerEdgeDistance); 183289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppendf( 184289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "} else {" 185289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon " %s = vec4(normalize(circleEdge.xy)," 186289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon " distanceToOuterEdge, %s);" 187289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "}", 188289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon args.fDistanceVectorName, innerEdgeDistance); 18968f2f7dc4229c3761dd5074a94c35878abcb9a36dvonbeck } 1904f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (cgp.fInClipPlane) { 191289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppend( 192289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "float clip = clamp(circleEdge.z * dot(circleEdge.xy, clipPlane.xy) + " 193289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "clipPlane.z, 0.0, 1.0);"); 1944f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (cgp.fInIsectPlane) { 195289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppend( 196289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "clip *= clamp(circleEdge.z * dot(circleEdge.xy, isectPlane.xy) + " 197289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "isectPlane.z, 0.0, 1.0);"); 1984f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 1994f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (cgp.fInUnionPlane) { 200289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppend( 201289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "clip += (1.0 - clip)*clamp(circleEdge.z * dot(circleEdge.xy, " 202289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "unionPlane.xy) + unionPlane.z, 0.0, 1.0);"); 2034f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 2044f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fragBuilder->codeAppend("edgeAlpha *= clip;"); 2054f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 2064ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); 20790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 20890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 20946d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static void GenKey(const GrGeometryProcessor& gp, 21094efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon const GrShaderCaps&, 211b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 212cdaa97bf664e0d584187efc125bfff670a064a9absalomon const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor>(); 2134f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon uint16_t key; 214289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon key = cgp.fStroke ? 0x01 : 0x0; 2154f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon key |= cgp.fLocalMatrix.hasPerspective() ? 0x02 : 0x0; 216289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon key |= cgp.fInClipPlane ? 0x04 : 0x0; 217289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon key |= cgp.fInIsectPlane ? 0x08 : 0x0; 218289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon key |= cgp.fInUnionPlane ? 0x10 : 0x0; 219b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt b->add32(key); 22090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 22190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 222a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, 223a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon FPCoordTransformIter&& transformIter) override { 224e4f2461113806e3080aeb8bc5637e82d1b3d8295bsalomon this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>().fLocalMatrix, 225a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon pdman, &transformIter); 226e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt } 227e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt 22890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 229e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel typedef GrGLSLGeometryProcessor INHERITED; 23090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 23190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 232289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkMatrix fLocalMatrix; 23371c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInPosition; 234bb2ff94e223014403f775c3532a25cc25b00c949brianosman const Attribute* fInColor; 23571c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInCircleEdge; 2364f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon const Attribute* fInClipPlane; 2374f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon const Attribute* fInIsectPlane; 2384f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon const Attribute* fInUnionPlane; 239289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fStroke; 24090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 241b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 24290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 243249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGeometryProcessor INHERITED; 24490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 24590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 246cdaa97bf664e0d584187efc125bfff670a064a9absalomonGR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor); 24790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 2486f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 24906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrGeometryProcessor> CircleGeometryProcessor::TestCreate(GrProcessorTestData* d) { 250289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return sk_sp<GrGeometryProcessor>(new CircleGeometryProcessor( 251289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon d->fRandom->nextBool(), d->fRandom->nextBool(), d->fRandom->nextBool(), 252289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon d->fRandom->nextBool(), GrTest::TestMatrix(d->fRandom))); 25390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 2546f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif 25590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 25690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 25790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 25890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/** 25990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org * The output of this effect is a modulation of the input color and coverage for an axis-aligned 2608be02fc2a72ae69a9142de68a483edf378aff1c8skia.committer@gmail.com * ellipse, specified as a 2D offset from center, and the reciprocals of the outer and inner radii, 2618be02fc2a72ae69a9142de68a483edf378aff1c8skia.committer@gmail.com * in both x and y directions. 2628be02fc2a72ae69a9142de68a483edf378aff1c8skia.committer@gmail.com * 2636bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. 26490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org */ 26590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 266cdaa97bf664e0d584187efc125bfff670a064a9absalomonclass EllipseGeometryProcessor : public GrGeometryProcessor { 26790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.orgpublic: 268289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon EllipseGeometryProcessor(bool stroke, const SkMatrix& localMatrix) : fLocalMatrix(localMatrix) { 269cdaa97bf664e0d584187efc125bfff670a064a9absalomon this->initClassID<EllipseGeometryProcessor>(); 2706cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType); 2716cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 2726cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInEllipseOffset = &this->addVertexAttrib("inEllipseOffset", kVec2f_GrVertexAttribType); 2736cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInEllipseRadii = &this->addVertexAttrib("inEllipseRadii", kVec4f_GrVertexAttribType); 274cdaa97bf664e0d584187efc125bfff670a064a9absalomon fStroke = stroke; 27590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 27690c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 277d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon ~EllipseGeometryProcessor() override {} 27890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 27936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "EllipseEdge"; } 2802dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 28194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 28231df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon GLSLProcessor::GenKey(*this, caps, b); 28331df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon } 28431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon 28594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 28631df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon return new GLSLProcessor(); 28731df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon } 28831df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon 28931df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomonprivate: 29057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel class GLSLProcessor : public GrGLSLGeometryProcessor { 29190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org public: 292bb2ff94e223014403f775c3532a25cc25b00c949brianosman GLSLProcessor() {} 29390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 294289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 295cdaa97bf664e0d584187efc125bfff670a064a9absalomon const EllipseGeometryProcessor& egp = args.fGP.cast<EllipseGeometryProcessor>(); 2964ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 2970eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 2987ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 29990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 300abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 301cdaa97bf664e0d584187efc125bfff670a064a9absalomon varyingHandler->emitAttributes(egp); 302abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 3038dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType); 3040eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets); 3054ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), 30631df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon egp.fInEllipseOffset->fName); 30790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 3088dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType); 3090eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->addVarying("EllipseRadii", &ellipseRadii); 310289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), egp.fInEllipseRadii->fName); 3112dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 3128528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 313b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt // setup pass through color 31431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon varyingHandler->addPassThroughAttribute(egp.fInColor, args.fOutputColor); 3159b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 316abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 31731df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon this->setupPosition(vertBuilder, gpArgs, egp.fInPosition->fName); 318abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 319abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 3207ea439b2203855db97330b25945b87dd4b170b8begdaniel this->emitTransforms(vertBuilder, 3210eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler, 3227ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 3234ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs->fPositionVar, 32431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon egp.fInPosition->fName, 32531df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon egp.fLocalMatrix, 326a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon args.fFPCoordTransformHandler); 3274973d9da4aeb7c4d8b8e67e167586c7cc9534eeejoshualitt 3288be02fc2a72ae69a9142de68a483edf378aff1c8skia.committer@gmail.com // for outer curve 3294ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(), 3304ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel ellipseRadii.fsIn()); 3314ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;"); 3324ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn()); 3334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); 33474077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt 3351b035d82d2b8b50ae334463edd06e4c5e0639311commit-bot@chromium.org // avoid calling inversesqrt on zero. 3364ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); 3374ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); 338c6052ac41a704cc64f16c49780a8fd05c7f550d4brianosman fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);"); 339f58d8540a42e5138e7cdb1dd1e0b4de0fa3c4a10jvanverth@google.com 3406bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org // for inner curve 341cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (egp.fStroke) { 342289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppendf("scaledOffset = %s*%s.zw;", ellipseOffsets.fsIn(), 3434ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel ellipseRadii.fsIn()); 344289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); 345289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", ellipseRadii.fsIn()); 3464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); 3474ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); 34890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 34990c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 3504ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); 35190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 35290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 35346d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static void GenKey(const GrGeometryProcessor& gp, 35494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon const GrShaderCaps&, 355b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 356cdaa97bf664e0d584187efc125bfff670a064a9absalomon const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcessor>(); 357cdaa97bf664e0d584187efc125bfff670a064a9absalomon uint16_t key = egp.fStroke ? 0x1 : 0x0; 35831df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon key |= egp.fLocalMatrix.hasPerspective() ? 0x2 : 0x0; 359b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt b->add32(key); 36090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org } 36190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 362a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc, 363a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon FPCoordTransformIter&& transformIter) override { 364a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon const EllipseGeometryProcessor& egp = primProc.cast<EllipseGeometryProcessor>(); 365a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon this->setTransformDataHelper(egp.fLocalMatrix, pdman, &transformIter); 366e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt } 367e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt 36890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org private: 369e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel typedef GrGLSLGeometryProcessor INHERITED; 37090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org }; 37190c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 37271c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInPosition; 373bb2ff94e223014403f775c3532a25cc25b00c949brianosman const Attribute* fInColor; 37471c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInEllipseOffset; 37571c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInEllipseRadii; 376e3ababe44315452cd33b96a18ce316ede09ff3c3joshualitt SkMatrix fLocalMatrix; 37790c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org bool fStroke; 37890c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 379b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 38090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 381249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGeometryProcessor INHERITED; 38290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org}; 38390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 384cdaa97bf664e0d584187efc125bfff670a064a9absalomonGR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseGeometryProcessor); 38590c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 3866f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 38706ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrGeometryProcessor> EllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) { 38806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman return sk_sp<GrGeometryProcessor>( 389289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon new EllipseGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatrix(d->fRandom))); 39090c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org} 3916f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif 39290c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 39390c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 39490c240aca0c0f4cd71bbde11f20c7949b2a37c1ecommit-bot@chromium.org 3955242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org/** 3966fc1b4998917791a73bf54428513940fe77dc058skia.committer@gmail.com * The output of this effect is a modulation of the input color and coverage for an ellipse, 3975242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org * specified as a 2D offset from center for both the outer and inner paths (if stroked). The 3985242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge corrected by 3995242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org * using differentials. 4005242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org * 4015242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org * The result is device-independent and can be used with any affine matrix. 4025242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org */ 4035242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 404cdaa97bf664e0d584187efc125bfff670a064a9absalomonenum class DIEllipseStyle { kStroke = 0, kHairline, kFill }; 4055242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 406cdaa97bf664e0d584187efc125bfff670a064a9absalomonclass DIEllipseGeometryProcessor : public GrGeometryProcessor { 407cdaa97bf664e0d584187efc125bfff670a064a9absalomonpublic: 408cdaa97bf664e0d584187efc125bfff670a064a9absalomon DIEllipseGeometryProcessor(const SkMatrix& viewMatrix, DIEllipseStyle style) 409289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon : fViewMatrix(viewMatrix) { 410cdaa97bf664e0d584187efc125bfff670a064a9absalomon this->initClassID<DIEllipseGeometryProcessor>(); 4116cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType, 4126cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon kHigh_GrSLPrecision); 4136cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType); 4146cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInEllipseOffsets0 = &this->addVertexAttrib("inEllipseOffsets0", kVec2f_GrVertexAttribType); 4156cb807bf99ac0f8f166e1790f91bcb3afbfb5458bsalomon fInEllipseOffsets1 = &this->addVertexAttrib("inEllipseOffsets1", kVec2f_GrVertexAttribType); 416cdaa97bf664e0d584187efc125bfff670a064a9absalomon fStyle = style; 4175242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } 4185242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 419d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon ~DIEllipseGeometryProcessor() override {} 4205242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 42136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "DIEllipseEdge"; } 4225242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 42394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 42431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon GLSLProcessor::GenKey(*this, caps, b); 42531df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon } 42631df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon 42794efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 42831df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon return new GLSLProcessor(); 42931df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon } 4309d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 43131df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomonprivate: 43257d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel class GLSLProcessor : public GrGLSLGeometryProcessor { 4335242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org public: 434289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GLSLProcessor() : fViewMatrix(SkMatrix::InvalidMatrix()) {} 4355242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 436465283cdf98ed9ab5285ca7b9814e430fca1d452joshualitt void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 437cdaa97bf664e0d584187efc125bfff670a064a9absalomon const DIEllipseGeometryProcessor& diegp = args.fGP.cast<DIEllipseGeometryProcessor>(); 4384ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 4390eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 4407ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 4415242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 442abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit attributes 443cdaa97bf664e0d584187efc125bfff670a064a9absalomon varyingHandler->emitAttributes(diegp); 444abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 4458dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag offsets0(kVec2f_GrSLType); 4460eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->addVarying("EllipseOffsets0", &offsets0); 447289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), diegp.fInEllipseOffsets0->fName); 44874077b9941ed3f73d92ba978ef29bf3e6f630cbcjoshualitt 4498dcdedc4a087ea46ce1e2458d335d60918e56310egdaniel GrGLSLVertToFrag offsets1(kVec2f_GrSLType); 4500eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler->addVarying("EllipseOffsets1", &offsets1); 451289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), diegp.fInEllipseOffsets1->fName); 4522dd1ae016d7f297b433c3ea3a771ef8e01657c1fjoshualitt 4538528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 45431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon varyingHandler->addPassThroughAttribute(diegp.fInColor, args.fOutputColor); 4559b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 456abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // Setup position 4577ea439b2203855db97330b25945b87dd4b170b8begdaniel this->setupPosition(vertBuilder, 4587ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 4594ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs, 46031df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon diegp.fInPosition->fName, 46131df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon diegp.fViewMatrix, 4625559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt &fViewMatrixUniform); 463abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt 464abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt // emit transforms 4657ea439b2203855db97330b25945b87dd4b170b8begdaniel this->emitTransforms(vertBuilder, 4660eafe79f42e3c675f3c504aed4a41abf511df2b7egdaniel varyingHandler, 4677ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler, 4684ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel gpArgs->fPositionVar, 46931df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon diegp.fInPosition->fName, 470a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon args.fFPCoordTransformHandler); 4714ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 4725242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org // for outer curve 4734ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn()); 4744ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;"); 4754ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn()); 4764ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn()); 477289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppendf( 478289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y," 479289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon " 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);", 480289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn(), offsets0.fsIn()); 4814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 4824ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); 4831b035d82d2b8b50ae334463edd06e4c5e0639311commit-bot@chromium.org // avoid calling inversesqrt on zero. 4844ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); 4854ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); 486cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (DIEllipseStyle::kHairline == diegp.fStyle) { 4875242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org // can probably do this with one step 4884ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);"); 4894ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);"); 4905242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } else { 4914ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);"); 4925242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } 4935242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 4945242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org // for inner curve 495cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (DIEllipseStyle::kStroke == diegp.fStyle) { 4964ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn()); 4974ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); 4984ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); 4994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); 500289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fragBuilder->codeAppendf( 501289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y," 502289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon " 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);", 503289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn(), offsets1.fsIn()); 5044ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); 5054ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); 5065242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } 5075242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 5084ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage); 5095242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } 5105242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 51146d36f0e7b709a077c647841eee23bd3efdc4117robertphillips static void GenKey(const GrGeometryProcessor& gp, 51294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon const GrShaderCaps&, 513b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrProcessorKeyBuilder* b) { 514cdaa97bf664e0d584187efc125bfff670a064a9absalomon const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>(); 515cdaa97bf664e0d584187efc125bfff670a064a9absalomon uint16_t key = static_cast<uint16_t>(diegp.fStyle); 51631df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon key |= ComputePosKey(diegp.fViewMatrix) << 10; 517b8c241ad099f3f0c2cbf3e7c10f5f6207175d490joshualitt b->add32(key); 5185242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } 5195242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 520a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp, 521a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon FPCoordTransformIter&& transformIter) override { 522cdaa97bf664e0d584187efc125bfff670a064a9absalomon const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>(); 5235559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt 52431df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon if (!diegp.fViewMatrix.isIdentity() && !fViewMatrix.cheapEqualTo(diegp.fViewMatrix)) { 52531df31c12fe2ce2a6688f226dd3ea24c06999f63bsalomon fViewMatrix = diegp.fViewMatrix; 526018fb62d12d1febf121fe265da5b6117b86a6541egdaniel float viewMatrix[3 * 3]; 52764c4728c70001ed074fecf5c4e083781987b12e9egdaniel GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 5285559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 5295559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt } 530a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); 5315242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org } 5325242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 5335242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org private: 5345559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt SkMatrix fViewMatrix; 5355559ca2a18687ef16b2fc92d8fcacbc1c3e93d54joshualitt UniformHandle fViewMatrixUniform; 5369b98932adaceb7ad0a617ade16616923f6bffe84joshualitt 537e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel typedef GrGLSLGeometryProcessor INHERITED; 5385242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org }; 5395242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 54071c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInPosition; 541bb2ff94e223014403f775c3532a25cc25b00c949brianosman const Attribute* fInColor; 54271c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInEllipseOffsets0; 54371c9260e6fa1798ad1e41b2c2ae9b3cce08bb610joshualitt const Attribute* fInEllipseOffsets1; 544289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkMatrix fViewMatrix; 545289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon DIEllipseStyle fStyle; 5465242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 547b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 5485242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 549249af15fb82833d2274850c589812b6e69df0033joshualitt typedef GrGeometryProcessor INHERITED; 5505242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org}; 5515242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 552cdaa97bf664e0d584187efc125bfff670a064a9absalomonGR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor); 5535242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 5546f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 55506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrGeometryProcessor> DIEllipseGeometryProcessor::TestCreate(GrProcessorTestData* d) { 556289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return sk_sp<GrGeometryProcessor>(new DIEllipseGeometryProcessor( 557289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrTest::TestMatrix(d->fRandom), (DIEllipseStyle)(d->fRandom->nextRangeU(0, 2)))); 5585242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org} 5596f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif 5605242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 5615242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 5625242ed761fc60470f31ffa6ea529c2a2f6afe6f5commit-bot@chromium.org 5636ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth// We have two possible cases for geometry for a circle: 5646ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 5656ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth// In the case of a normal fill, we draw geometry for the circle as an octagon. 5666ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const uint16_t gFillCircleIndices[] = { 567289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // enter the octagon 568289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // clang-format off 569289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 0, 1, 8, 1, 2, 8, 570289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 2, 3, 8, 3, 4, 8, 571289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 4, 5, 8, 5, 6, 8, 572289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 6, 7, 8, 7, 0, 8 573289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // clang-format on 5746ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth}; 5756ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 5766ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth// For stroked circles, we use two nested octagons. 5776ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const uint16_t gStrokeCircleIndices[] = { 578289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // enter the octagon 579289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // clang-format off 580289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 0, 1, 9, 0, 9, 8, 581289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 1, 2, 10, 1, 10, 9, 582289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 2, 3, 11, 2, 11, 10, 583289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 3, 4, 12, 3, 12, 11, 584289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 4, 5, 13, 4, 13, 12, 585289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 5, 6, 14, 5, 14, 13, 586289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 6, 7, 15, 6, 15, 14, 587289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 7, 0, 8, 7, 8, 15, 588289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // clang-format on 5896ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth}; 5906ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 591289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 5926ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const int kIndicesPerFillCircle = SK_ARRAY_COUNT(gFillCircleIndices); 5936ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const int kIndicesPerStrokeCircle = SK_ARRAY_COUNT(gStrokeCircleIndices); 5946ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const int kVertsPerStrokeCircle = 16; 5956ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const int kVertsPerFillCircle = 9; 5966ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 5976ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic int circle_type_to_vert_count(bool stroked) { 5986ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth return stroked ? kVertsPerStrokeCircle : kVertsPerFillCircle; 5996ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth} 6006ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 6016ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic int circle_type_to_index_count(bool stroked) { 6026ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth return stroked ? kIndicesPerStrokeCircle : kIndicesPerFillCircle; 6036ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth} 6046ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 6056ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverthstatic const uint16_t* circle_type_to_indices(bool stroked) { 6066ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth return stroked ? gStrokeCircleIndices : gFillCircleIndices; 6076ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth} 6086ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 6096ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth/////////////////////////////////////////////////////////////////////////////// 6106ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 611289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonclass CircleOp final : public GrMeshDrawOp { 6124b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomonpublic: 61325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 614f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 6154f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon /** Optional extra params to render a partial arc rather than a full circle. */ 6164f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon struct ArcParams { 6174f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fStartAngleRadians; 6184f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fSweepAngleRadians; 6194f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon bool fUseCenter; 6204f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon }; 621649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix, 622649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkPoint center, SkScalar radius, const GrStyle& style, 623649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const ArcParams* arcParams = nullptr) { 6244f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkASSERT(circle_stays_circle(viewMatrix)); 6254f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon const SkStrokeRec& stroke = style.strokeRec(); 6264f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (style.hasPathEffect()) { 6274f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon return nullptr; 6284f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 6294f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkStrokeRec::Style recStyle = stroke.getStyle(); 6304f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (arcParams) { 6314f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // Arc support depends on the style. 6324f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon switch (recStyle) { 6334f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon case SkStrokeRec::kStrokeAndFill_Style: 634289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // This produces a strange result that this op doesn't implement. 6354f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon return nullptr; 6364f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon case SkStrokeRec::kFill_Style: 6374f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // This supports all fills. 6384f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon break; 639289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case SkStrokeRec::kStroke_Style: // fall through 6404f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon case SkStrokeRec::kHairline_Style: 6414f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // Strokes that don't use the center point are supported with butt cap. 6424f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (arcParams->fUseCenter || stroke.getCap() != SkPaint::kButt_Cap) { 6434f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon return nullptr; 6444f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 6454f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon break; 6464f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 6474f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 6484f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 6494b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon viewMatrix.mapPoints(¢er, 1); 6504f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon radius = viewMatrix.mapRadius(radius); 6514b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); 6521b55a963a2374a14bb82eb887bb99ee91680f0ebreed 653289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool isStrokeOnly = 654289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkStrokeRec::kStroke_Style == recStyle || SkStrokeRec::kHairline_Style == recStyle; 6554f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == recStyle; 65676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 6576ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkScalar innerRadius = -SK_ScalarHalf; 6584b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar outerRadius = radius; 6594b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar halfWidth = 0; 6604b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (hasStroke) { 6614b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkScalarNearlyZero(strokeWidth)) { 6624b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon halfWidth = SK_ScalarHalf; 6634b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } else { 6644b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon halfWidth = SkScalarHalf(strokeWidth); 6654b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 6665fd209e8ee477c703bc5c11b008f247d515fc0fcbsalomon 6674b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon outerRadius += halfWidth; 6684b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (isStrokeOnly) { 6694b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerRadius = radius - halfWidth; 6704b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 6714b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 6727f06c6947a3bef78dc57b9252779567c33604c90bsalomon 6734b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // The radii are outset for two reasons. First, it allows the shader to simply perform 6744b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // simpler computation because the computed alpha is zero, rather than 50%, at the radius. 6754b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // Second, the outer radius is used to compute the verts of the bounding box that is 6764b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // rendered and the outset ensures the box will cover all partially covered by the circle. 6774b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon outerRadius += SK_ScalarHalf; 6784b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerRadius -= SK_ScalarHalf; 6796ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth bool stroked = isStrokeOnly && innerRadius > 0.0f; 680f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon std::unique_ptr<CircleOp> op(new CircleOp()); 681289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fViewMatrixIfUsingLocalCoords = viewMatrix; 68211bf8b2eae7d1780cb969146422a2ab3b933047absalomon 6834f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // This makes every point fully inside the intersection plane. 6844f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f}; 6854f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // This makes every point fully outside the union plane. 6864f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon static constexpr SkScalar kUnusedUnionPlane[] = {0.f, 0.f, 0.f}; 6874f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkRect devBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius, 6884f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon center.fX + outerRadius, center.fY + outerRadius); 6894f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (arcParams) { 6904f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // The shader operates in a space where the circle is translated to be centered at the 6914f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // origin. Here we compute points on the unit circle at the starting and ending angles. 6924f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkPoint startPoint, stopPoint; 6934f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon startPoint.fY = SkScalarSinCos(arcParams->fStartAngleRadians, &startPoint.fX); 6944f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar endAngle = arcParams->fStartAngleRadians + arcParams->fSweepAngleRadians; 6954f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon stopPoint.fY = SkScalarSinCos(endAngle, &stopPoint.fX); 6964f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // Like a fill without useCenter, butt-cap stroke can be implemented by clipping against 6974f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // radial lines. However, in both cases we have to be careful about the half-circle. 6984f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // case. In that case the two radial lines are equal and so that edge gets clipped 6994f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // twice. Since the shared edge goes through the center we fall back on the useCenter 7004f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // case. 701289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool useCenter = 702289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (arcParams->fUseCenter || isStrokeOnly) && 703289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon !SkScalarNearlyEqual(SkScalarAbs(arcParams->fSweepAngleRadians), SK_ScalarPI); 7044f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (useCenter) { 7054f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkVector norm0 = {startPoint.fY, -startPoint.fX}; 7064f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkVector norm1 = {stopPoint.fY, -stopPoint.fX}; 7074f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (arcParams->fSweepAngleRadians > 0) { 7084f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon norm0.negate(); 7094f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 7104f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon norm1.negate(); 7114f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 712289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlane = true; 7134f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (SkScalarAbs(arcParams->fSweepAngleRadians) > SK_ScalarPI) { 714289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back(Geometry{ 7154f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon color, 7164f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon innerRadius, 7174f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon outerRadius, 7184f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon {norm0.fX, norm0.fY, 0.5f}, 7194f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]}, 7204f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon {norm1.fX, norm1.fY, 0.5f}, 7216ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth devBounds, 722289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon stroked}); 723289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneIsect = false; 724289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneUnion = true; 7254f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 726289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back(Geometry{ 7274f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon color, 7284f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon innerRadius, 7294f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon outerRadius, 7304f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon {norm0.fX, norm0.fY, 0.5f}, 7314f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon {norm1.fX, norm1.fY, 0.5f}, 7324f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]}, 7336ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth devBounds, 734289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon stroked}); 735289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneIsect = true; 736289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneUnion = false; 7374f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 7384f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 7394f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // We clip to a secant of the original circle. 7404f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon startPoint.scale(radius); 7414f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon stopPoint.scale(radius); 7424f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkVector norm = {startPoint.fY - stopPoint.fY, stopPoint.fX - startPoint.fX}; 7434f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon norm.normalize(); 7444f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (arcParams->fSweepAngleRadians > 0) { 7454f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon norm.negate(); 7464f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 7474f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar d = -norm.dot(startPoint) + 0.5f; 7484f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 749289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back( 750289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon Geometry{color, 751289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon innerRadius, 752289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon outerRadius, 753289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {norm.fX, norm.fY, d}, 754289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]}, 755289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]}, 756289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon devBounds, 757289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon stroked}); 758289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlane = true; 759289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneIsect = false; 760289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneUnion = false; 7614f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 7624f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } else { 763289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back( 764289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon Geometry{color, 765289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon innerRadius, 766289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon outerRadius, 767289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]}, 768289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2]}, 769289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2]}, 770289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon devBounds, 771289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon stroked}); 772289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlane = false; 773289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneIsect = false; 774289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fClipPlaneUnion = false; 7754f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 77688cf17d099085b8085ab11571b5094163dbb2c84bsalomon // Use the original radius and stroke radius for the bounds so that it does not include the 77788cf17d099085b8085ab11571b5094163dbb2c84bsalomon // AA bloat. 77888cf17d099085b8085ab11571b5094163dbb2c84bsalomon radius += halfWidth; 779289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->setBounds( 780289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon {center.fX - radius, center.fY - radius, center.fX + radius, center.fY + radius}, 781289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon HasAABloat::kYes, IsZeroArea::kNo); 782289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fVertCount = circle_type_to_vert_count(stroked); 783289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fIndexCount = circle_type_to_index_count(stroked); 784289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fAllFill = !stroked; 785289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return std::move(op); 786c79fc33d3e83664ffbd3651df3131c3e9e0b635chush } 7874b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 788289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const char* name() const override { return "CircleOp"; } 78976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 790e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips SkString dumpInfo() const override { 791e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips SkString string; 792e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips for (int i = 0; i < fGeoData.count(); ++i) { 793289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon string.appendf( 794289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]," 795289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "InnerRad: %.2f, OuterRad: %.2f\n", 796289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData[i].fColor, fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.fTop, 797289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds.fBottom, 798289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData[i].fInnerRadius, fGeoData[i].fOuterRadius); 799e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips } 8007c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 801e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips string.append(INHERITED::dumpInfo()); 802e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips return string; 803e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips } 804e004bfc0a5e28cc083158f1a75e981ffd58a8134robertphillips 805e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate: 806289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleOp() : INHERITED(ClassID()) {} 80792aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 808c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 809c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 810c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fGeoData[0].fColor); 811c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 81292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 81392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 81492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 81592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fGeoData[0].fColor); 81692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (!optimizations.readsLocalCoords()) { 817cdaa97bf664e0d584187efc125bfff670a064a9absalomon fViewMatrixIfUsingLocalCoords.reset(); 818cdaa97bf664e0d584187efc125bfff670a064a9absalomon } 81976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 82076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 821144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt void onPrepareDraws(Target* target) const override { 822cdaa97bf664e0d584187efc125bfff670a064a9absalomon SkMatrix localMatrix; 823cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 82476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return; 82576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 82676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 82776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Setup geometry processor 828289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon sk_sp<GrGeometryProcessor> gp(new CircleGeometryProcessor( 829289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon !fAllFill, fClipPlane, fClipPlaneIsect, fClipPlaneUnion, localMatrix)); 8304f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 8314f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon struct CircleVertex { 832289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fPos; 833289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrColor fColor; 834289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fOffset; 8354f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fOuterRadius; 8364f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fInnerRadius; 8374f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon // These planes may or may not be present in the vertex buffer. 8384f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fHalfPlanes[3][3]; 8394f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon }; 84076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 84176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt int instanceCount = fGeoData.count(); 84276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt size_t vertexStride = gp->getVertexStride(); 843289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkASSERT(vertexStride == 844289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * sizeof(SkScalar)) - 845289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (fClipPlaneIsect ? 0 : 3 * sizeof(SkScalar)) - 846289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (fClipPlaneUnion ? 0 : 3 * sizeof(SkScalar))); 8476ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 8486ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth const GrBuffer* vertexBuffer; 8496ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth int firstVertex; 850289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon char* vertices = (char*)target->makeVertexSpace(vertexStride, fVertCount, &vertexBuffer, 851289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon &firstVertex); 8524f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (!vertices) { 8536ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkDebugf("Could not allocate vertices\n"); 8546ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth return; 8556ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 8566ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 8576ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth const GrBuffer* indexBuffer = nullptr; 8586ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth int firstIndex = 0; 8596ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth uint16_t* indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex); 8606ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (!indices) { 8616ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkDebugf("Could not allocate indices\n"); 8624b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt return; 8634b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt } 8644b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt 8656ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth int currStartVertex = 0; 86676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < instanceCount; i++) { 867144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt const Geometry& geom = fGeoData[i]; 86876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 869bb2ff94e223014403f775c3532a25cc25b00c949brianosman GrColor color = geom.fColor; 870b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar innerRadius = geom.fInnerRadius; 871b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar outerRadius = geom.fOuterRadius; 87276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 873b5238a7571c243ba4a154a62575570c3078b3741bsalomon const SkRect& bounds = geom.fDevBounds; 874289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + 0 * vertexStride); 875289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + 1 * vertexStride); 876289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + 2 * vertexStride); 877289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + 3 * vertexStride); 878289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v4 = reinterpret_cast<CircleVertex*>(vertices + 4 * vertexStride); 879289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v5 = reinterpret_cast<CircleVertex*>(vertices + 5 * vertexStride); 880289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v6 = reinterpret_cast<CircleVertex*>(vertices + 6 * vertexStride); 881289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* v7 = reinterpret_cast<CircleVertex*>(vertices + 7 * vertexStride); 88276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 88376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // The inner radius in the vertex data must be specified in normalized space. 88476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt innerRadius = innerRadius / outerRadius; 8856ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 8866ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkPoint center = SkPoint::Make(bounds.centerX(), bounds.centerY()); 887289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar halfWidth = 0.5f * bounds.width(); 8886ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkScalar octOffset = 0.41421356237f; // sqrt(2) - 1 88960c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby 890289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v0->fPos = center + SkPoint::Make(-octOffset * halfWidth, -halfWidth); 8914f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v0->fColor = color; 8926ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v0->fOffset = SkPoint::Make(-octOffset, -1); 8934f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v0->fOuterRadius = outerRadius; 8944f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v0->fInnerRadius = innerRadius; 8954f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 896289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v1->fPos = center + SkPoint::Make(octOffset * halfWidth, -halfWidth); 8974f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v1->fColor = color; 8986ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v1->fOffset = SkPoint::Make(octOffset, -1); 8994f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v1->fOuterRadius = outerRadius; 9004f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v1->fInnerRadius = innerRadius; 9014f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 902289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v2->fPos = center + SkPoint::Make(halfWidth, -octOffset * halfWidth); 9034f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v2->fColor = color; 9046ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v2->fOffset = SkPoint::Make(1, -octOffset); 9054f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v2->fOuterRadius = outerRadius; 9064f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v2->fInnerRadius = innerRadius; 9074f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 908289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v3->fPos = center + SkPoint::Make(halfWidth, octOffset * halfWidth); 9094f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v3->fColor = color; 9106ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v3->fOffset = SkPoint::Make(1, octOffset); 9114f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v3->fOuterRadius = outerRadius; 9124f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon v3->fInnerRadius = innerRadius; 9134f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 914289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v4->fPos = center + SkPoint::Make(octOffset * halfWidth, halfWidth); 9156ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fColor = color; 9166ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fOffset = SkPoint::Make(octOffset, 1); 9176ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fOuterRadius = outerRadius; 9186ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fInnerRadius = innerRadius; 9196ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 920289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v5->fPos = center + SkPoint::Make(-octOffset * halfWidth, halfWidth); 9216ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fColor = color; 9226ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fOffset = SkPoint::Make(-octOffset, 1); 9236ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fOuterRadius = outerRadius; 9246ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fInnerRadius = innerRadius; 9256ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 926289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v6->fPos = center + SkPoint::Make(-halfWidth, octOffset * halfWidth); 9276ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fColor = color; 9286ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fOffset = SkPoint::Make(-1, octOffset); 9296ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fOuterRadius = outerRadius; 9306ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fInnerRadius = innerRadius; 9316ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 932289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v7->fPos = center + SkPoint::Make(-halfWidth, -octOffset * halfWidth); 9336ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fColor = color; 9346ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fOffset = SkPoint::Make(-1, -octOffset); 9356ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fOuterRadius = outerRadius; 9366ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fInnerRadius = innerRadius; 9376ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 9384f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (fClipPlane) { 9394f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9404f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9414f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9424f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9436ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v4->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9446ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v5->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9456ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v6->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9466ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v7->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 9474f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 9484f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon int unionIdx = 1; 9494f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (fClipPlaneIsect) { 9504f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9514f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9524f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9534f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9546ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v4->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9556ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v5->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9566ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v6->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9576ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v7->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 9584f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon unionIdx = 2; 9594f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 9604f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (fClipPlaneUnion) { 9614f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9624f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9634f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9644f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9656ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v4->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9666ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v5->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9676ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v6->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9686ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v7->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 9696ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 9706ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 9716ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (geom.fStroked) { 9726ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth // compute the inner ring 9736ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride); 9746ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + 9 * vertexStride); 9756ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + 10 * vertexStride); 9766ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + 11 * vertexStride); 9776ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v4 = reinterpret_cast<CircleVertex*>(vertices + 12 * vertexStride); 9786ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v5 = reinterpret_cast<CircleVertex*>(vertices + 13 * vertexStride); 9796ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v6 = reinterpret_cast<CircleVertex*>(vertices + 14 * vertexStride); 9806ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v7 = reinterpret_cast<CircleVertex*>(vertices + 15 * vertexStride); 9816ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 9826ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth // cosine and sine of pi/8 9836ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkScalar c = 0.923579533f; 9846ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkScalar s = 0.382683432f; 9856ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkScalar r = geom.fInnerRadius; 9866ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 987289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v0->fPos = center + SkPoint::Make(-s * r, -c * r); 9886ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v0->fColor = color; 989289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v0->fOffset = SkPoint::Make(-s * innerRadius, -c * innerRadius); 9906ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v0->fOuterRadius = outerRadius; 9916ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v0->fInnerRadius = innerRadius; 9926ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 993289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v1->fPos = center + SkPoint::Make(s * r, -c * r); 9946ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v1->fColor = color; 995289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v1->fOffset = SkPoint::Make(s * innerRadius, -c * innerRadius); 9966ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v1->fOuterRadius = outerRadius; 9976ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v1->fInnerRadius = innerRadius; 9986ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 999289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v2->fPos = center + SkPoint::Make(c * r, -s * r); 10006ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v2->fColor = color; 1001289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v2->fOffset = SkPoint::Make(c * innerRadius, -s * innerRadius); 10026ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v2->fOuterRadius = outerRadius; 10036ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v2->fInnerRadius = innerRadius; 10046ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 1005289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v3->fPos = center + SkPoint::Make(c * r, s * r); 10066ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v3->fColor = color; 1007289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v3->fOffset = SkPoint::Make(c * innerRadius, s * innerRadius); 10086ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v3->fOuterRadius = outerRadius; 10096ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v3->fInnerRadius = innerRadius; 10106ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 1011289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v4->fPos = center + SkPoint::Make(s * r, c * r); 10126ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fColor = color; 1013289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v4->fOffset = SkPoint::Make(s * innerRadius, c * innerRadius); 10146ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fOuterRadius = outerRadius; 10156ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v4->fInnerRadius = innerRadius; 10166ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 1017289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v5->fPos = center + SkPoint::Make(-s * r, c * r); 10186ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fColor = color; 1019289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v5->fOffset = SkPoint::Make(-s * innerRadius, c * innerRadius); 10206ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fOuterRadius = outerRadius; 10216ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v5->fInnerRadius = innerRadius; 10226ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 1023289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v6->fPos = center + SkPoint::Make(-c * r, s * r); 10246ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fColor = color; 1025289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v6->fOffset = SkPoint::Make(-c * innerRadius, s * innerRadius); 10266ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fOuterRadius = outerRadius; 10276ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v6->fInnerRadius = innerRadius; 10286ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 1029289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v7->fPos = center + SkPoint::Make(-c * r, -s * r); 10306ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fColor = color; 1031289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon v7->fOffset = SkPoint::Make(-c * innerRadius, -s * innerRadius); 10326ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fOuterRadius = outerRadius; 10336ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v7->fInnerRadius = innerRadius; 10346ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 10356ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (fClipPlane) { 10366ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10376ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10386ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10396ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10406ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v4->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10416ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v5->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10426ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v6->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10436ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v7->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10446ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10456ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth int unionIdx = 1; 10466ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (fClipPlaneIsect) { 10476ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10486ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10496ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10506ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10516ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v4->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10526ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v5->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10536ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v6->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10546ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v7->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10556ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth unionIdx = 2; 10566ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10576ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (fClipPlaneUnion) { 10586ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10596ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10606ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10616ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10626ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v4->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10636ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v5->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10646ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v6->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10656ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v7->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10666ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10676ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } else { 10686ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth // filled 10696ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth CircleVertex* v8 = reinterpret_cast<CircleVertex*>(vertices + 8 * vertexStride); 10706ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v8->fPos = center; 10716ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v8->fColor = color; 10726ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v8->fOffset = SkPoint::Make(0, 0); 10736ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v8->fOuterRadius = outerRadius; 10746ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth v8->fInnerRadius = innerRadius; 10756ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (fClipPlane) { 10766ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v8->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar)); 10776ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10786ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth int unionIdx = 1; 10796ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (fClipPlaneIsect) { 10806ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v8->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar)); 10816ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth unionIdx = 2; 10826ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10836ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (fClipPlaneUnion) { 10846ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth memcpy(v8->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(SkScalar)); 10856ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10864f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 10876ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 10886ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth const uint16_t* primIndices = circle_type_to_indices(geom.fStroked); 10896ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth const int primIndexCount = circle_type_to_index_count(geom.fStroked); 10906ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth for (int i = 0; i < primIndexCount; ++i) { 10916ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth *indices++ = primIndices[i] + currStartVertex; 10926ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth } 10936ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 10946ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth currStartVertex += circle_type_to_vert_count(geom.fStroked); 1095289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon vertices += circle_type_to_vert_count(geom.fStroked) * vertexStride; 109676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 10976ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth 10986ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth GrMesh mesh; 10996ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, 11006ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth firstIndex, fVertCount, fIndexCount); 11016ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth target->draw(gp.get(), mesh); 110276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 110376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 110425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 1105289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleOp* that = t->cast<CircleOp>(); 11068cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth 11078cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth // can only represent 65535 unique vertices with 16-bit indices 1108e549a05dc20c84597b324b19b9764136da54e5f1Jim Van Verth if (fVertCount + that->fVertCount > 65536) { 11098cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth return false; 11108cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth } 11118cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth 1112abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 1113abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon that->bounds(), caps)) { 11148cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 11158cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 11168cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 11176ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { 111876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 111976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 112076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1121289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // Because we've set up the ops that don't use the planes with noop values 1122289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // we can just accumulate used planes by later ops. 11234f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fClipPlane |= that->fClipPlane; 11244f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fClipPlaneIsect |= that->fClipPlaneIsect; 11254f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon fClipPlaneUnion |= that->fClipPlaneUnion; 11264f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 1127cdaa97bf664e0d584187efc125bfff670a064a9absalomon fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 112888cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 11296ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth fVertCount += that->fVertCount; 11306ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth fIndexCount += that->fIndexCount; 11316ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth fAllFill = fAllFill && that->fAllFill; 113276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return true; 113376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 113476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 11354b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon struct Geometry { 1136289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrColor fColor; 11374b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerRadius; 11384b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fOuterRadius; 11394f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fClipPlane[3]; 11404f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fIsectPlane[3]; 11414f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar fUnionPlane[3]; 1142289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkRect fDevBounds; 1143289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fStroked; 11444b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon }; 11454b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 11466ca48820407244bbdeb8f9e0ed7d76dd94270460jvanverth SkSTArray<1, Geometry, true> fGeoData; 1147289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkMatrix fViewMatrixIfUsingLocalCoords; 1148289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon int fVertCount; 1149289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon int fIndexCount; 1150289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fAllFill; 1151289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fClipPlane; 1152289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fClipPlaneIsect; 1153289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fClipPlaneUnion; 11541b55a963a2374a14bb82eb887bb99ee91680f0ebreed 1155dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 115676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt}; 115776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1158f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 1159f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1160289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonclass EllipseOp : public GrMeshDrawOp { 116176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualittpublic: 116225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 1163649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix, 1164649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRect& ellipse, const SkStrokeRec& stroke) { 11654b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkASSERT(viewMatrix.rectStaysRect()); 11664b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 11674b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // do any matrix crunching before we reset the draw state for device coords 11684b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); 11694b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon viewMatrix.mapPoints(¢er, 1); 11704b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar ellipseXRadius = SkScalarHalf(ellipse.width()); 11714b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar ellipseYRadius = SkScalarHalf(ellipse.height()); 1172289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX] * ellipseXRadius + 1173289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon viewMatrix[SkMatrix::kMSkewY] * ellipseYRadius); 1174289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX] * ellipseXRadius + 1175289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon viewMatrix[SkMatrix::kMScaleY] * ellipseYRadius); 11764b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 11774b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // do (potentially) anisotropic mapping of stroke 11784b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkVector scaledStroke; 11794b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar strokeWidth = stroke.getWidth(); 1180289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon scaledStroke.fX = SkScalarAbs( 1181289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon strokeWidth * (viewMatrix[SkMatrix::kMScaleX] + viewMatrix[SkMatrix::kMSkewY])); 1182289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon scaledStroke.fY = SkScalarAbs( 1183289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon strokeWidth * (viewMatrix[SkMatrix::kMSkewX] + viewMatrix[SkMatrix::kMScaleY])); 11844b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 11854b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkStrokeRec::Style style = stroke.getStyle(); 1186289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool isStrokeOnly = 1187289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style; 11884b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; 11894b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 11904b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerXRadius = 0; 11914b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerYRadius = 0; 11924b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (hasStroke) { 11934b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkScalarNearlyZero(scaledStroke.length())) { 11944b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 11954b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } else { 11964b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon scaledStroke.scale(SK_ScalarHalf); 11974b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 11985fd209e8ee477c703bc5c11b008f247d515fc0fcbsalomon 11994b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we only handle thick strokes for near-circular ellipses 12004b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (scaledStroke.length() > SK_ScalarHalf && 1201289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (SK_ScalarHalf * xRadius > yRadius || SK_ScalarHalf * yRadius > xRadius)) { 12024b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 12034b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 120411bf8b2eae7d1780cb969146422a2ab3b933047absalomon 12054b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we don't handle it if curvature of the stroke is less than curvature of the ellipse 1206289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (scaledStroke.fX * (yRadius * yRadius) < 1207289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (scaledStroke.fY * scaledStroke.fY) * xRadius || 1208289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon scaledStroke.fY * (xRadius * xRadius) < 1209289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (scaledStroke.fX * scaledStroke.fX) * yRadius) { 12104b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 12114b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 12124b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 12134b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // this is legit only if scale & translation (which should be the case at the moment) 12144b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (isStrokeOnly) { 12154b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerXRadius = xRadius - scaledStroke.fX; 12164b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerYRadius = yRadius - scaledStroke.fY; 12174b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 12184b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 12194b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon xRadius += scaledStroke.fX; 12204b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon yRadius += scaledStroke.fY; 12214b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 12224b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1223f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon std::unique_ptr<EllipseOp> op(new EllipseOp()); 1224289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back( 1225289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon Geometry{color, xRadius, yRadius, innerXRadius, innerYRadius, 1226289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRadius, 1227289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon center.fX + xRadius, center.fY + yRadius)}); 12284b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1229289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->setBounds(op->fGeoData.back().fDevBounds, HasAABloat::kYes, IsZeroArea::kNo); 123088cf17d099085b8085ab11571b5094163dbb2c84bsalomon 12314b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // Outset bounds to include half-pixel width antialiasing. 1232289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData[0].fDevBounds.outset(SK_ScalarHalf, SK_ScalarHalf); 12334b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1234289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fStroked = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; 1235289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fViewMatrixIfUsingLocalCoords = viewMatrix; 1236289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return std::move(op); 1237cdaa97bf664e0d584187efc125bfff670a064a9absalomon } 123876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1239289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const char* name() const override { return "EllipseOp"; } 124076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 12417c3e7180948766321c51d165737555e78910de51Brian Salomon SkString dumpInfo() const override { 12427c3e7180948766321c51d165737555e78910de51Brian Salomon SkString string; 12437c3e7180948766321c51d165737555e78910de51Brian Salomon string.appendf("Stroked: %d\n", fStroked); 12447c3e7180948766321c51d165737555e78910de51Brian Salomon for (const auto& geo : fGeoData) { 1245289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon string.appendf( 1246289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], " 1247289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "XRad: %.2f, YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f\n", 1248289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fColor, geo.fDevBounds.fLeft, geo.fDevBounds.fTop, geo.fDevBounds.fRight, 1249289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fDevBounds.fBottom, geo.fXRadius, geo.fYRadius, geo.fInnerXRadius, 1250289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fInnerYRadius); 12517c3e7180948766321c51d165737555e78910de51Brian Salomon } 12527c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 12537c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(INHERITED::dumpInfo()); 12547c3e7180948766321c51d165737555e78910de51Brian Salomon return string; 12557c3e7180948766321c51d165737555e78910de51Brian Salomon } 12567c3e7180948766321c51d165737555e78910de51Brian Salomon 1257e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate: 1258289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon EllipseOp() : INHERITED(ClassID()) {} 12594b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1260c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 1261c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 1262c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fGeoData[0].fColor); 1263c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 126492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 126592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 126692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 126792aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (!optimizations.readsLocalCoords()) { 1268cdaa97bf664e0d584187efc125bfff670a064a9absalomon fViewMatrixIfUsingLocalCoords.reset(); 1269cdaa97bf664e0d584187efc125bfff670a064a9absalomon } 127076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 127176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1272144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt void onPrepareDraws(Target* target) const override { 1273cdaa97bf664e0d584187efc125bfff670a064a9absalomon SkMatrix localMatrix; 1274cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 127576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return; 127676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 127776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 127876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Setup geometry processor 1279144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix)); 128076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 128176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt int instanceCount = fGeoData.count(); 1282b5238a7571c243ba4a154a62575570c3078b3741bsalomon QuadHelper helper; 128376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt size_t vertexStride = gp->getVertexStride(); 128419e0058a650a9e4dc9c35ed26c5e91916bcc0601joshualitt SkASSERT(vertexStride == sizeof(EllipseVertex)); 1285289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon EllipseVertex* verts = 1286289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon reinterpret_cast<EllipseVertex*>(helper.init(target, vertexStride, instanceCount)); 1287b5238a7571c243ba4a154a62575570c3078b3741bsalomon if (!verts) { 12884b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt return; 12894b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt } 12904b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt 129176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < instanceCount; i++) { 1292144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt const Geometry& geom = fGeoData[i]; 129376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1294bb2ff94e223014403f775c3532a25cc25b00c949brianosman GrColor color = geom.fColor; 1295b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar xRadius = geom.fXRadius; 1296b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar yRadius = geom.fYRadius; 129776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 129876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Compute the reciprocals of the radii here to save time in the shader 129976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar xRadRecip = SkScalarInvert(xRadius); 130076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar yRadRecip = SkScalarInvert(yRadius); 1301b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar xInnerRadRecip = SkScalarInvert(geom.fInnerXRadius); 1302b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar yInnerRadRecip = SkScalarInvert(geom.fInnerYRadius); 130376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1304b5238a7571c243ba4a154a62575570c3078b3741bsalomon const SkRect& bounds = geom.fDevBounds; 130576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1306977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack // fOffsets are expanded from xyRadii to include the half-pixel antialiasing width. 1307977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack SkScalar xMaxOffset = xRadius + SK_ScalarHalf; 1308977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack SkScalar yMaxOffset = yRadius + SK_ScalarHalf; 1309977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack 131076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // The inner radius in the vertex data must be specified in normalized space. 1311289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); 1312bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[0].fColor = color; 1313977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack verts[0].fOffset = SkPoint::Make(-xMaxOffset, -yMaxOffset); 131476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[0].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 131576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[0].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 131676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1317289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); 1318bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[1].fColor = color; 1319977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack verts[1].fOffset = SkPoint::Make(-xMaxOffset, yMaxOffset); 132076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[1].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 132176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[1].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 132276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 132376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 1324bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[2].fColor = color; 1325977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack verts[2].fOffset = SkPoint::Make(xMaxOffset, yMaxOffset); 132676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[2].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 132776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[2].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 132876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 132976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 1330bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[3].fColor = color; 1331977996dd0e0c6e6686a980a23e97e6fb5da1a592vjiaoblack verts[3].fOffset = SkPoint::Make(xMaxOffset, -yMaxOffset); 133276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 133376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 133476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1335b5238a7571c243ba4a154a62575570c3078b3741bsalomon verts += kVerticesPerQuad; 133676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 1337144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary helper.recordDraw(target, gp.get()); 133876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 133976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 134025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 1341289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon EllipseOp* that = t->cast<EllipseOp>(); 1342abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 1343abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 1344abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon that->bounds(), caps)) { 13458cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 13468cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 13478cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 1348cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (fStroked != that->fStroked) { 134976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 135076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 135176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1352cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { 135376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 135476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 135576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1356cdaa97bf664e0d584187efc125bfff670a064a9absalomon fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 135788cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 135876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return true; 135976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 136076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 13614b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon struct Geometry { 13624b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon GrColor fColor; 13634b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fXRadius; 13644b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fYRadius; 13654b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerXRadius; 13664b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerYRadius; 13674b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkRect fDevBounds; 13684b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon }; 136976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1370289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fStroked; 1371289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkMatrix fViewMatrixIfUsingLocalCoords; 137276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkSTArray<1, Geometry, true> fGeoData; 13731b55a963a2374a14bb82eb887bb99ee91680f0ebreed 1374dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 137576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt}; 137676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 13774b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon///////////////////////////////////////////////////////////////////////////////////////////////// 13786bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org 1379289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonclass DIEllipseOp : public GrMeshDrawOp { 13804b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomonpublic: 138125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 13826bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org 1383649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, 1384649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 1385649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRect& ellipse, 1386649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke) { 13874b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); 13884b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar xRadius = SkScalarHalf(ellipse.width()); 13894b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar yRadius = SkScalarHalf(ellipse.height()); 13904b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 13914b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkStrokeRec::Style style = stroke.getStyle(); 1392289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon DIEllipseStyle dieStyle = (SkStrokeRec::kStroke_Style == style) 1393289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon ? DIEllipseStyle::kStroke 1394289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon : (SkStrokeRec::kHairline_Style == style) 1395289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon ? DIEllipseStyle::kHairline 1396289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon : DIEllipseStyle::kFill; 13974b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 13984b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerXRadius = 0; 13994b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerYRadius = 0; 14004b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != style) { 14014b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar strokeWidth = stroke.getWidth(); 14024b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 14034b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkScalarNearlyZero(strokeWidth)) { 14044b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon strokeWidth = SK_ScalarHalf; 14054b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } else { 14064b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon strokeWidth *= SK_ScalarHalf; 14074b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 14086bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org 14094b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we only handle thick strokes for near-circular ellipses 14104b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (strokeWidth > SK_ScalarHalf && 1411289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (SK_ScalarHalf * xRadius > yRadius || SK_ScalarHalf * yRadius > xRadius)) { 14124b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 14134b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 1414fc5b70a8e427ee115868786fa361c2c813ab566bbenjaminwagner 14154b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we don't handle it if curvature of the stroke is less than curvature of the ellipse 1416289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (strokeWidth * (yRadius * yRadius) < (strokeWidth * strokeWidth) * xRadius || 1417289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon strokeWidth * (xRadius * xRadius) < (strokeWidth * strokeWidth) * yRadius) { 14184b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 14194b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 1420df4f47b8ff6378c4d8f775dcb3169ac7c64f2510benjaminwagner 14214b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // set inner radius (if needed) 14224b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkStrokeRec::kStroke_Style == style) { 14234b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerXRadius = xRadius - strokeWidth; 14244b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerYRadius = yRadius - strokeWidth; 14254b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 1426c79fc33d3e83664ffbd3651df3131c3e9e0b635chush 14274b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon xRadius += strokeWidth; 14284b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon yRadius += strokeWidth; 14294b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 14304b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (DIEllipseStyle::kStroke == dieStyle) { 1431289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon dieStyle = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseStyle::kStroke 1432289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon : DIEllipseStyle::kFill; 14336bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org } 14346bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org 14354b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // This expands the outer rect so that after CTM we end up with a half-pixel border 14364b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar a = viewMatrix[SkMatrix::kMScaleX]; 14374b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar b = viewMatrix[SkMatrix::kMSkewX]; 14384b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar c = viewMatrix[SkMatrix::kMSkewY]; 14394b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar d = viewMatrix[SkMatrix::kMScaleY]; 1440289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a * a + c * c); 1441289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b * b + d * d); 1442289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 1443f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon std::unique_ptr<DIEllipseOp> op(new DIEllipseOp()); 1444289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back(Geometry{ 1445289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon viewMatrix, color, xRadius, yRadius, innerXRadius, innerYRadius, geoDx, geoDy, 1446289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon dieStyle, 1447289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy, 1448289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon center.fX + xRadius + geoDx, center.fY + yRadius + geoDy)}); 1449289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->setTransformedBounds(op->fGeoData[0].fBounds, viewMatrix, HasAABloat::kYes, 1450289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon IsZeroArea::kNo); 1451289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return std::move(op); 145276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 145376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1454289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const char* name() const override { return "DIEllipseOp"; } 145576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 14567c3e7180948766321c51d165737555e78910de51Brian Salomon SkString dumpInfo() const override { 14577c3e7180948766321c51d165737555e78910de51Brian Salomon SkString string; 14587c3e7180948766321c51d165737555e78910de51Brian Salomon for (const auto& geo : fGeoData) { 1459289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon string.appendf( 1460289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], XRad: %.2f, " 1461289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f, GeoDX: %.2f, " 1462289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "GeoDY: %.2f\n", 1463289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fColor, geo.fBounds.fLeft, geo.fBounds.fTop, geo.fBounds.fRight, 1464289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fBounds.fBottom, geo.fXRadius, geo.fYRadius, geo.fInnerXRadius, 1465289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fInnerYRadius, geo.fGeoDx, geo.fGeoDy); 14667c3e7180948766321c51d165737555e78910de51Brian Salomon } 14677c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 14687c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(INHERITED::dumpInfo()); 14697c3e7180948766321c51d165737555e78910de51Brian Salomon return string; 14707c3e7180948766321c51d165737555e78910de51Brian Salomon } 14717c3e7180948766321c51d165737555e78910de51Brian Salomon 1472e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate: 1473289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon DIEllipseOp() : INHERITED(ClassID()) {} 14744b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1475c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 1476c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 1477c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fGeoData[0].fColor); 1478c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 147992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 148092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 148192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 148292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fGeoData[0].fColor); 148392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fUsesLocalCoords = optimizations.readsLocalCoords(); 148476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 148576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1486144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt void onPrepareDraws(Target* target) const override { 148776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Setup geometry processor 1488289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon sk_sp<GrGeometryProcessor> gp( 1489289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon new DIEllipseGeometryProcessor(this->viewMatrix(), this->style())); 149076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 149176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt int instanceCount = fGeoData.count(); 149276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt size_t vertexStride = gp->getVertexStride(); 149319e0058a650a9e4dc9c35ed26c5e91916bcc0601joshualitt SkASSERT(vertexStride == sizeof(DIEllipseVertex)); 1494b5238a7571c243ba4a154a62575570c3078b3741bsalomon QuadHelper helper; 1495b5238a7571c243ba4a154a62575570c3078b3741bsalomon DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>( 1496289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon helper.init(target, vertexStride, instanceCount)); 1497b5238a7571c243ba4a154a62575570c3078b3741bsalomon if (!verts) { 14984b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt return; 14994b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt } 15004b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt 150176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < instanceCount; i++) { 1502144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt const Geometry& geom = fGeoData[i]; 150376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1504bb2ff94e223014403f775c3532a25cc25b00c949brianosman GrColor color = geom.fColor; 1505b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar xRadius = geom.fXRadius; 1506b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkScalar yRadius = geom.fYRadius; 150776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1508b5238a7571c243ba4a154a62575570c3078b3741bsalomon const SkRect& bounds = geom.fBounds; 150976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 151076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // This adjusts the "radius" to include the half-pixel border 151180ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar offsetDx = geom.fGeoDx / xRadius; 151280ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar offsetDy = geom.fGeoDy / yRadius; 151376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 151480ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar innerRatioX = xRadius / geom.fInnerXRadius; 151580ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed SkScalar innerRatioY = yRadius / geom.fInnerYRadius; 151676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 151776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); 1518bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[0].fColor = color; 151976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[0].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy); 152076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[0].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, -innerRatioY - offsetDy); 152176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1522289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); 1523bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[1].fColor = color; 152476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[1].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy); 152576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[1].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, innerRatioY + offsetDy); 152676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 152776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 1528bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[2].fColor = color; 152976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[2].fOuterOffset = SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy); 153076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[2].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, innerRatioY + offsetDy); 153176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 153276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 1533bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts[3].fColor = color; 153476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy); 153576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy); 153676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1537b5238a7571c243ba4a154a62575570c3078b3741bsalomon verts += kVerticesPerQuad; 153876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 1539144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary helper.recordDraw(target, gp.get()); 154076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 15419d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 154225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 1543289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon DIEllipseOp* that = t->cast<DIEllipseOp>(); 1544abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 1545abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon that->bounds(), caps)) { 15468cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 15478cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 15488cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 1549cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (this->style() != that->style()) { 155076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 155176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 155276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1553d96a67bcb196aa4f73ff773bd45810a94ca872d8joshualitt // TODO rewrite to allow positioning on CPU 1554d96a67bcb196aa4f73ff773bd45810a94ca872d8joshualitt if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 155576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 155676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 155776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1558cdaa97bf664e0d584187efc125bfff670a064a9absalomon fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 155988cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 156076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return true; 156176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 156276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 156376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } 1564cdaa97bf664e0d584187efc125bfff670a064a9absalomon DIEllipseStyle style() const { return fGeoData[0].fStyle; } 156576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 15664b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon struct Geometry { 15674b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkMatrix fViewMatrix; 15684b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon GrColor fColor; 15694b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fXRadius; 15704b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fYRadius; 15714b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerXRadius; 15724b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerYRadius; 15734b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fGeoDx; 15744b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fGeoDy; 15754b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon DIEllipseStyle fStyle; 15764b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkRect fBounds; 15774b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon }; 15784b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1579289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fUsesLocalCoords; 158076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkSTArray<1, Geometry, true> fGeoData; 15811b55a963a2374a14bb82eb887bb99ee91680f0ebreed 1582dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 158376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt}; 1584f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1585f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 1586f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 1587fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein// We have three possible cases for geometry for a roundrect. 1588c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// 1589c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// In the case of a normal fill or a stroke, we draw the roundrect as a 9-patch: 1590c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// ____________ 1591c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// |_|________|_| 1592c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// | | | | 1593c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// | | | | 1594c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// | | | | 1595c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// |_|________|_| 1596c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// |_|________|_| 1597c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// 1598c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// For strokes, we don't draw the center quad. 1599c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// 1600c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// For circular roundrects, in the case where the stroke width is greater than twice 1601c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// the corner radius (overstroke), we add additional geometry to mark out the rectangle 16026a3976114d8a6aaa564c3c7571cfe7d1727a3a6ejvanverth// in the center. The shared vertices are duplicated so we can set a different outer radius 16036a3976114d8a6aaa564c3c7571cfe7d1727a3a6ejvanverth// for the fill calculation. 1604c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// ____________ 1605c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// |_|________|_| 1606c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// | |\ ____ /| | 1607c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// | | | | | | 1608c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// | | |____| | | 1609c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// |_|/______\|_| 1610c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// |_|________|_| 1611c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// 1612c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth// We don't draw the center quad from the fill rect in this case. 161379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// 161479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// For filled rrects that need to provide a distance vector we resuse the overstroke 161579839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// geometry but make the inner rect degenerate (either a point or a horizontal or 161679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// vertical line). 1617c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth 161884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic const uint16_t gOverstrokeRRectIndices[] = { 1619289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // clang-format off 1620289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // overstroke quads 1621289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // we place this at the beginning so that we can skip these indices when rendering normally 1622289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 16, 17, 19, 16, 19, 18, 1623289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 19, 17, 23, 19, 23, 21, 1624289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 21, 23, 22, 21, 22, 20, 1625289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 22, 16, 18, 22, 18, 20, 1626289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 1627289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // corners 1628289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 0, 1, 5, 0, 5, 4, 1629289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 2, 3, 7, 2, 7, 6, 1630289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 8, 9, 13, 8, 13, 12, 1631289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 10, 11, 15, 10, 15, 14, 1632289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 1633289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // edges 1634289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 1, 2, 6, 1, 6, 5, 1635289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 4, 5, 9, 4, 9, 8, 1636289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 6, 7, 11, 6, 11, 10, 1637289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 9, 10, 14, 9, 14, 13, 1638289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 1639289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // center 1640289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // we place this at the end so that we can ignore these indices when not rendering as filled 1641289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 5, 6, 10, 5, 10, 9, 1642289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // clang-format on 1643f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org}; 1644289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon 164584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth// fill and standard stroke indices skip the overstroke "ring" 1646289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonstatic const uint16_t* gStandardRRectIndices = gOverstrokeRRectIndices + 6 * 4; 1647f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 164884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth// overstroke count is arraysize minus the center indices 164984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic const int kIndicesPerOverstrokeRRect = SK_ARRAY_COUNT(gOverstrokeRRectIndices) - 6; 165084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth// fill count skips overstroke indices and includes center 1651289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonstatic const int kIndicesPerFillRRect = kIndicesPerOverstrokeRRect - 6 * 4 + 6; 165284839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth// stroke count is fill count minus center indices 1653c3d0e422761702c52a974411eaf0b06d223fe98ejvanverthstatic const int kIndicesPerStrokeRRect = kIndicesPerFillRRect - 6; 1654c3d0e422761702c52a974411eaf0b06d223fe98ejvanverthstatic const int kVertsPerStandardRRect = 16; 16556a3976114d8a6aaa564c3c7571cfe7d1727a3a6ejvanverthstatic const int kVertsPerOverstrokeRRect = 24; 16565ead6da4abaa3d8fb479fd84631138f83b7aa5b6joshualitt 1657c3d0e422761702c52a974411eaf0b06d223fe98ejvanverthenum RRectType { 1658c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth kFill_RRectType, 1659c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth kStroke_RRectType, 166084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth kOverstroke_RRectType, 166179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips kFillWithDist_RRectType 1662c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth}; 1663c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth 166484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic int rrect_type_to_vert_count(RRectType type) { 1665289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon switch (type) { 1666289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kFill_RRectType: 1667289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kStroke_RRectType: 1668289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return kVertsPerStandardRRect; 1669289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kOverstroke_RRectType: 1670289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kFillWithDist_RRectType: 1671289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return kVertsPerOverstrokeRRect; 1672289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon } 1673289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkFAIL("Invalid type"); 1674289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return 0; 167584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth} 167684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 167784839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic int rrect_type_to_index_count(RRectType type) { 1678289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon switch (type) { 1679289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kFill_RRectType: 1680289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return kIndicesPerFillRRect; 1681289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kStroke_RRectType: 1682289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return kIndicesPerStrokeRRect; 1683289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kOverstroke_RRectType: 1684289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kFillWithDist_RRectType: 1685289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return kIndicesPerOverstrokeRRect; 1686289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon } 1687289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkFAIL("Invalid type"); 1688289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return 0; 168984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth} 169084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 169184839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic const uint16_t* rrect_type_to_indices(RRectType type) { 1692289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon switch (type) { 1693289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kFill_RRectType: 1694289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kStroke_RRectType: 1695289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return gStandardRRectIndices; 1696289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kOverstroke_RRectType: 1697289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon case kFillWithDist_RRectType: 1698289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return gOverstrokeRRectIndices; 1699289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon } 1700289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkFAIL("Invalid type"); 1701289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return 0; 1702ed0bcad9c8147fd37c23bdda00ec27ec9ef8d66bbsalomon} 1703ed0bcad9c8147fd37c23bdda00ec27ec9ef8d66bbsalomon 170476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt/////////////////////////////////////////////////////////////////////////////////////////////////// 170576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 170679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// For distance computations in the interior of filled rrects we: 170779839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// 170879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// add a interior degenerate (point or line) rect 170979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// each vertex of that rect gets -outerRad as its radius 171079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// this makes the computation of the distance to the outer edge be negative 171179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// negative values are caught and then handled differently in the GP's onEmitCode 171279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// each vertex is also given the normalized x & y distance from the interior rect's edge 171379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips// the GP takes the min of those depths +1 to get the normalized distance to the outer edge 171479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 1715289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonclass CircularRRectOp : public GrMeshDrawOp { 171676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualittpublic: 171725a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 17181b55a963a2374a14bb82eb887bb99ee91680f0ebreed 17194b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then strokeOnly indicates 17204b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // whether the rrect is only stroked or stroked and filled. 1721289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircularRRectOp(GrColor color, bool needsDistance, const SkMatrix& viewMatrix, 1722289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const SkRect& devRect, float devRadius, float devStrokeWidth, bool strokeOnly) 1723289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon : INHERITED(ClassID()), fViewMatrixIfUsingLocalCoords(viewMatrix) { 17244b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkRect bounds = devRect; 17254b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); 17264b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerRadius = 0.0f; 17274b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar outerRadius = devRadius; 17284b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar halfWidth = 0; 172984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth RRectType type = kFill_RRectType; 17304b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (devStrokeWidth > 0) { 17314b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkScalarNearlyZero(devStrokeWidth)) { 17324b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon halfWidth = SK_ScalarHalf; 17334b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } else { 17344b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon halfWidth = SkScalarHalf(devStrokeWidth); 17354b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 173611bf8b2eae7d1780cb969146422a2ab3b933047absalomon 17374b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (strokeOnly) { 1738c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // Outset stroke by 1/4 pixel 1739c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth devStrokeWidth += 0.25f; 1740c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // If stroke is greater than width or height, this is still a fill 1741c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // Otherwise we compute stroke params 1742289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (devStrokeWidth <= devRect.width() && devStrokeWidth <= devRect.height()) { 1743c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth innerRadius = devRadius - halfWidth; 174484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth type = (innerRadius >= 0) ? kStroke_RRectType : kOverstroke_RRectType; 1745c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth } 17464b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 17474b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon outerRadius += halfWidth; 17484b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon bounds.outset(halfWidth, halfWidth); 17494b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 175079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips if (kFill_RRectType == type && needsDistance) { 175179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips type = kFillWithDist_RRectType; 175279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips } 175311bf8b2eae7d1780cb969146422a2ab3b933047absalomon 17544b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // The radii are outset for two reasons. First, it allows the shader to simply perform 17554b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // simpler computation because the computed alpha is zero, rather than 50%, at the radius. 17564b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // Second, the outer radius is used to compute the verts of the bounding box that is 17574b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // rendered and the outset ensures the box will cover all partially covered by the rrect 17584b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // corners. 17594b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon outerRadius += SK_ScalarHalf; 17604b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerRadius -= SK_ScalarHalf; 17614b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 176288cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo); 176388cf17d099085b8085ab11571b5094163dbb2c84bsalomon 176488cf17d099085b8085ab11571b5094163dbb2c84bsalomon // Expand the rect for aa to generate correct vertices. 17654b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 17664b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 1767289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData.emplace_back(Geometry{color, innerRadius, outerRadius, bounds, type}); 176884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth fVertCount = rrect_type_to_vert_count(type); 176984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth fIndexCount = rrect_type_to_index_count(type); 177084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth fAllFill = (kFill_RRectType == type); 177176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 177276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1773289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const char* name() const override { return "CircularRRectOp"; } 177476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1775c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth SkString dumpInfo() const override { 1776c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth SkString string; 1777c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth for (int i = 0; i < fGeoData.count(); ++i) { 1778289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon string.appendf( 1779289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]," 1780289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "InnerRad: %.2f, OuterRad: %.2f\n", 1781289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData[i].fColor, fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds.fTop, 1782289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds.fBottom, 1783289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fGeoData[i].fInnerRadius, fGeoData[i].fOuterRadius); 1784c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth } 17857c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 1786c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth string.append(INHERITED::dumpInfo()); 1787c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth return string; 1788c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth } 1789c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth 179092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomonprivate: 1791c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 1792c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 1793c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fGeoData[0].fColor); 1794c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 179576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 179676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 179792aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 179892aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fGeoData[0].fColor); 179992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (!optimizations.readsLocalCoords()) { 1800cdaa97bf664e0d584187efc125bfff670a064a9absalomon fViewMatrixIfUsingLocalCoords.reset(); 1801cdaa97bf664e0d584187efc125bfff670a064a9absalomon } 180276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 180376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 180479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips struct CircleVertex { 1805289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fPos; 1806289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrColor fColor; 1807289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkPoint fOffset; 180879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips SkScalar fOuterRadius; 180979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips SkScalar fInnerRadius; 181079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips // No half plane, we don't use it here. 181179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips }; 181279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 1813289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon static void FillInOverstrokeVerts(CircleVertex** verts, const SkRect& bounds, SkScalar smInset, 1814289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar bigInset, SkScalar xOffset, SkScalar outerRadius, 1815289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar innerRadius, GrColor color) { 181679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips SkASSERT(smInset < bigInset); 181779839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 181879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips // TL 181979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fPos = SkPoint::Make(bounds.fLeft + smInset, bounds.fTop + smInset); 182079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 182179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(xOffset, 0); 182279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18233786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 182479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 182579839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 182679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips // TR 1827289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (*verts)->fPos = SkPoint::Make(bounds.fRight - smInset, bounds.fTop + smInset); 182879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 182979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(xOffset, 0); 183079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18313786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 183279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 183379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 1834289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (*verts)->fPos = SkPoint::Make(bounds.fLeft + bigInset, bounds.fTop + bigInset); 183579839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 183679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(0, 0); 183779839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18383786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 183979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 184079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 1841289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (*verts)->fPos = SkPoint::Make(bounds.fRight - bigInset, bounds.fTop + bigInset); 184279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 184379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(0, 0); 184479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18453786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 184679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 184779839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 184879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fPos = SkPoint::Make(bounds.fLeft + bigInset, bounds.fBottom - bigInset); 184979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 185079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(0, 0); 185179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18523786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 185379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 185479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 185579839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fPos = SkPoint::Make(bounds.fRight - bigInset, bounds.fBottom - bigInset); 185679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 185779839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(0, 0); 185879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18593786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 186079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 186179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 186279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips // BL 186379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fPos = SkPoint::Make(bounds.fLeft + smInset, bounds.fBottom - smInset); 186479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 186579839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(xOffset, 0); 186679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18673786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 186879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 186979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 187079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips // BR 187179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fPos = SkPoint::Make(bounds.fRight - smInset, bounds.fBottom - smInset); 187279839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fColor = color; 187379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOffset = SkPoint::Make(xOffset, 0); 187479839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)->fOuterRadius = outerRadius; 18753786c7716c4796146835e60d7145cff252ed50bdRobert Phillips (*verts)->fInnerRadius = innerRadius; 187679839d45f893ad5690fc83c951567b3686e781e6Robert Phillips (*verts)++; 187779839d45f893ad5690fc83c951567b3686e781e6Robert Phillips } 187879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 1879144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt void onPrepareDraws(Target* target) const override { 1880cdaa97bf664e0d584187efc125bfff670a064a9absalomon // Invert the view matrix as a local matrix (if any other processors require coords). 1881cdaa97bf664e0d584187efc125bfff670a064a9absalomon SkMatrix localMatrix; 1882cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 188376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return; 188476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 188576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 188676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Setup geometry processor 1887289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon sk_sp<GrGeometryProcessor> gp( 1888289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon new CircleGeometryProcessor(!fAllFill, false, false, false, localMatrix)); 188976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 189076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt int instanceCount = fGeoData.count(); 189176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt size_t vertexStride = gp->getVertexStride(); 189284839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth SkASSERT(sizeof(CircleVertex) == vertexStride); 189384839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 189484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth const GrBuffer* vertexBuffer; 189584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth int firstVertex; 189684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 1897289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleVertex* verts = (CircleVertex*)target->makeVertexSpace(vertexStride, fVertCount, 1898289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon &vertexBuffer, &firstVertex); 189984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth if (!verts) { 19004b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt SkDebugf("Could not allocate vertices\n"); 19014b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt return; 19024b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt } 19034b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt 190484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth const GrBuffer* indexBuffer = nullptr; 190584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth int firstIndex = 0; 190684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth uint16_t* indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex); 190784839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth if (!indices) { 190884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth SkDebugf("Could not allocate indices\n"); 190984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth return; 191084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth } 191184839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 191284839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth int currStartVertex = 0; 191376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < instanceCount; i++) { 1914144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt const Geometry& args = fGeoData[i]; 191576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1916bb2ff94e223014403f775c3532a25cc25b00c949brianosman GrColor color = args.fColor; 191776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar outerRadius = args.fOuterRadius; 191876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1919bc227140ffea6eb15e2e8b147eb6d8ec6228d95aegdaniel const SkRect& bounds = args.fDevBounds; 192076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1921289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar yCoords[4] = {bounds.fTop, bounds.fTop + outerRadius, 1922289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bounds.fBottom - outerRadius, bounds.fBottom}; 192376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 1924289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar yOuterRadii[4] = {-1, 0, 0, 1}; 192576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // The inner radius in the vertex data must be specified in normalized space. 192684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth // For fills, specifying -1/outerRadius guarantees an alpha of 1.0 at the inner radius. 1927289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar innerRadius = 1928289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon args.fType != kFill_RRectType && args.fType != kFillWithDist_RRectType 1929289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon ? args.fInnerRadius / args.fOuterRadius 1930289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon : -1.0f / args.fOuterRadius; 193176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < 4; ++i) { 193276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); 1933bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 193476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]); 193576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadius = outerRadius; 193676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadius = innerRadius; 193776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 193876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 193976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]); 1940bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 194176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); 194276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadius = outerRadius; 194376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadius = innerRadius; 194476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 194576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 194676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i]); 1947bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 194876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); 194976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadius = outerRadius; 195076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadius = innerRadius; 195176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 195276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 195376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 1954bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 195576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); 195676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadius = outerRadius; 195776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadius = innerRadius; 195876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 195976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 1960c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // Add the additional vertices for overstroked rrects. 1961a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // Effectively this is an additional stroked rrect, with its 1962a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // outer radius = outerRadius - innerRadius, and inner radius = 0. 1963a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // This will give us correct AA in the center and the correct 1964a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // distance to the outer edge. 1965c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // 1966a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // Also, the outer offset is a constant vector pointing to the right, which 1967a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // guarantees that the distance value along the outer rectangle is constant. 196884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth if (kOverstroke_RRectType == args.fType) { 196979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips SkASSERT(args.fInnerRadius <= 0.0f); 197079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips 1971a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth SkScalar overstrokeOuterRadius = outerRadius - args.fInnerRadius; 1972a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // this is the normalized distance from the outer rectangle of this 1973a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth // geometry to the outer edge 197484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth SkScalar maxOffset = -args.fInnerRadius / overstrokeOuterRadius; 1975a4f1af8f9778462184c2bef91de1b1827568c08bjvanverth 1976289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon FillInOverstrokeVerts(&verts, bounds, outerRadius, overstrokeOuterRadius, maxOffset, 1977289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon overstrokeOuterRadius, 0.0f, color); 197879839d45f893ad5690fc83c951567b3686e781e6Robert Phillips } 1979c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth 198079839d45f893ad5690fc83c951567b3686e781e6Robert Phillips if (kFillWithDist_RRectType == args.fType) { 198179839d45f893ad5690fc83c951567b3686e781e6Robert Phillips SkScalar halfMinDim = 0.5f * SkTMin(bounds.width(), bounds.height()); 19826a3976114d8a6aaa564c3c7571cfe7d1727a3a6ejvanverth 198379839d45f893ad5690fc83c951567b3686e781e6Robert Phillips SkScalar xOffset = 1.0f - outerRadius / halfMinDim; 19846a3976114d8a6aaa564c3c7571cfe7d1727a3a6ejvanverth 1985289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon FillInOverstrokeVerts(&verts, bounds, outerRadius, halfMinDim, xOffset, halfMinDim, 1986289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon -1.0f, color); 1987c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth } 198884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 198984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth const uint16_t* primIndices = rrect_type_to_indices(args.fType); 199084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth const int primIndexCount = rrect_type_to_index_count(args.fType); 199184839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth for (int i = 0; i < primIndexCount; ++i) { 199284839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth *indices++ = primIndices[i] + currStartVertex; 199384839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth } 199484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 199584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth currStartVertex += rrect_type_to_vert_count(args.fType); 199676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 199776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 199884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth GrMesh mesh; 199984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, 200084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth firstIndex, fVertCount, fIndexCount); 200184839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth target->draw(gp.get(), mesh); 200276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 200376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 200425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 2005289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircularRRectOp* that = t->cast<CircularRRectOp>(); 20068cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth 20078cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth // can only represent 65535 unique vertices with 16-bit indices 2008e549a05dc20c84597b324b19b9764136da54e5f1Jim Van Verth if (fVertCount + that->fVertCount > 65536) { 20098cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth return false; 20108cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth } 20118cefe40ab094bfbea532761dad1a857eb3d4b831Jim Van Verth 2012abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 2013abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon that->bounds(), caps)) { 20148cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 20158cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 20168cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 2017cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { 201876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 201976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 202076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2021cdaa97bf664e0d584187efc125bfff670a064a9absalomon fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 202288cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 202384839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth fVertCount += that->fVertCount; 202484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth fIndexCount += that->fIndexCount; 202584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth fAllFill = fAllFill && that->fAllFill; 202676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return true; 202776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 202876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 20294b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon struct Geometry { 2030289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon GrColor fColor; 20314b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerRadius; 20324b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fOuterRadius; 20334b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkRect fDevBounds; 203484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth RRectType fType; 20354b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon }; 20364b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 203776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkSTArray<1, Geometry, true> fGeoData; 2038289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkMatrix fViewMatrixIfUsingLocalCoords; 2039289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon int fVertCount; 2040289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon int fIndexCount; 2041289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fAllFill; 20421b55a963a2374a14bb82eb887bb99ee91680f0ebreed 2043dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 204476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt}; 204576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 204684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic const int kNumRRectsInIndexBuffer = 256; 204784839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 204884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthGR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); 204984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthGR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); 205084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverthstatic const GrBuffer* ref_rrect_index_buffer(RRectType type, 205184839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth GrResourceProvider* resourceProvider) { 205284839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); 205384839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); 205484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth switch (type) { 205584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth case kFill_RRectType: 205684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth return resourceProvider->findOrCreateInstancedIndexBuffer( 2057289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon gStandardRRectIndices, kIndicesPerFillRRect, kNumRRectsInIndexBuffer, 2058289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon kVertsPerStandardRRect, gRRectOnlyIndexBufferKey); 205984839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth case kStroke_RRectType: 206084839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth return resourceProvider->findOrCreateInstancedIndexBuffer( 2061289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon gStandardRRectIndices, kIndicesPerStrokeRRect, kNumRRectsInIndexBuffer, 2062289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon kVertsPerStandardRRect, gStrokeRRectOnlyIndexBufferKey); 206384839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth default: 206484839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth SkASSERT(false); 206584839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth return nullptr; 206684839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth }; 206784839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth} 206884839f6fb3d0de9088be3d53e81df195331ed1c9jvanverth 2069289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomonclass EllipticalRRectOp : public GrMeshDrawOp { 207076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualittpublic: 207125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 20721b55a963a2374a14bb82eb887bb99ee91680f0ebreed 20734b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, strokeOnly indicates 20744b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // whether the rrect is only stroked or stroked and filled. 2075649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix, 2076649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRect& devRect, float devXRadius, 2077649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon float devYRadius, SkVector devStrokeWidths, 2078649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon bool strokeOnly) { 20794b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkASSERT(devXRadius > 0.5); 20804b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkASSERT(devYRadius > 0.5); 20814b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkASSERT((devStrokeWidths.fX > 0) == (devStrokeWidths.fY > 0)); 20824b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkASSERT(!(strokeOnly && devStrokeWidths.fX <= 0)); 20834b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerXRadius = 0.0f; 20844b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar innerYRadius = 0.0f; 20854b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkRect bounds = devRect; 20864b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon bool stroked = false; 20874b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (devStrokeWidths.fX > 0) { 20884b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (SkScalarNearlyZero(devStrokeWidths.length())) { 20894b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon devStrokeWidths.set(SK_ScalarHalf, SK_ScalarHalf); 20904b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } else { 20914b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon devStrokeWidths.scale(SK_ScalarHalf); 20924b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 20934b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 20944b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we only handle thick strokes for near-circular ellipses 20954b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (devStrokeWidths.length() > SK_ScalarHalf && 2096289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (SK_ScalarHalf * devXRadius > devYRadius || 2097289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SK_ScalarHalf * devYRadius > devXRadius)) { 20984b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 20994b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 21004b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 21014b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we don't handle it if curvature of the stroke is less than curvature of the ellipse 2102289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (devStrokeWidths.fX * (devYRadius * devYRadius) < 2103289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (devStrokeWidths.fY * devStrokeWidths.fY) * devXRadius) { 21044b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 21054b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 2106289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (devStrokeWidths.fY * (devXRadius * devXRadius) < 2107289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon (devStrokeWidths.fX * devStrokeWidths.fX) * devYRadius) { 21084b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 21094b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 211011bf8b2eae7d1780cb969146422a2ab3b933047absalomon 21114b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // this is legit only if scale & translation (which should be the case at the moment) 21124b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (strokeOnly) { 21134b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerXRadius = devXRadius - devStrokeWidths.fX; 21144b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon innerYRadius = devYRadius - devStrokeWidths.fY; 21154b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon stroked = (innerXRadius >= 0 && innerYRadius >= 0); 21164b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 21174b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 21184b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon devXRadius += devStrokeWidths.fX; 21194b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon devYRadius += devStrokeWidths.fY; 21204b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon bounds.outset(devStrokeWidths.fX, devStrokeWidths.fY); 21214b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 21224b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 2123f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon std::unique_ptr<EllipticalRRectOp> op(new EllipticalRRectOp()); 2124289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fStroked = stroked; 2125289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fViewMatrixIfUsingLocalCoords = viewMatrix; 2126289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo); 212788cf17d099085b8085ab11571b5094163dbb2c84bsalomon // Expand the rect for aa in order to generate the correct vertices. 212888cf17d099085b8085ab11571b5094163dbb2c84bsalomon bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 2129289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon op->fGeoData.emplace_back( 2130289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon Geometry{color, devXRadius, devYRadius, innerXRadius, innerYRadius, bounds}); 2131289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return std::move(op); 213276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 213376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2134289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const char* name() const override { return "EllipticalRRectOp"; } 213576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 21367c3e7180948766321c51d165737555e78910de51Brian Salomon SkString dumpInfo() const override { 21377c3e7180948766321c51d165737555e78910de51Brian Salomon SkString string; 21387c3e7180948766321c51d165737555e78910de51Brian Salomon string.appendf("Stroked: %d\n", fStroked); 21397c3e7180948766321c51d165737555e78910de51Brian Salomon for (const auto& geo : fGeoData) { 2140289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon string.appendf( 2141289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], " 2142289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon "XRad: %.2f, YRad: %.2f, InnerXRad: %.2f, InnerYRad: %.2f\n", 2143289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fColor, geo.fDevBounds.fLeft, geo.fDevBounds.fTop, geo.fDevBounds.fRight, 2144289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fDevBounds.fBottom, geo.fXRadius, geo.fYRadius, geo.fInnerXRadius, 2145289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon geo.fInnerYRadius); 21467c3e7180948766321c51d165737555e78910de51Brian Salomon } 21477c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 21487c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(INHERITED::dumpInfo()); 21497c3e7180948766321c51d165737555e78910de51Brian Salomon return string; 21507c3e7180948766321c51d165737555e78910de51Brian Salomon } 21517c3e7180948766321c51d165737555e78910de51Brian Salomon 2152e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate: 2153289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon EllipticalRRectOp() : INHERITED(ClassID()) {} 21544b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 2155c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 2156c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 2157c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fGeoData[0].fColor); 2158c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 215992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 216092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 216192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 216292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fGeoData[0].fColor); 216392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon if (!optimizations.readsLocalCoords()) { 2164cdaa97bf664e0d584187efc125bfff670a064a9absalomon fViewMatrixIfUsingLocalCoords.reset(); 2165cdaa97bf664e0d584187efc125bfff670a064a9absalomon } 216676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 216776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2168144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt void onPrepareDraws(Target* target) const override { 2169cdaa97bf664e0d584187efc125bfff670a064a9absalomon SkMatrix localMatrix; 2170cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 217176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return; 217276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 217376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 217476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Setup geometry processor 2175144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix)); 217676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 217776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt int instanceCount = fGeoData.count(); 217876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt size_t vertexStride = gp->getVertexStride(); 217976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkASSERT(vertexStride == sizeof(EllipseVertex)); 218076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2181b5238a7571c243ba4a154a62575570c3078b3741bsalomon // drop out the middle quad if we're stroked 2182c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPerFillRRect; 2183289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon sk_sp<const GrBuffer> indexBuffer(ref_rrect_index_buffer( 2184289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon fStroked ? kStroke_RRectType : kFill_RRectType, target->resourceProvider())); 218576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2186b5238a7571c243ba4a154a62575570c3078b3741bsalomon InstancedHelper helper; 2187b5238a7571c243ba4a154a62575570c3078b3741bsalomon EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( 2188289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(), 2189289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon kVertsPerStandardRRect, indicesPerInstance, instanceCount)); 2190b5238a7571c243ba4a154a62575570c3078b3741bsalomon if (!verts || !indexBuffer) { 21914b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt SkDebugf("Could not allocate vertices\n"); 21924b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt return; 21934b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt } 21944b31de8328bbf3ee789157ae1dc6fe7cc74c796ajoshualitt 219576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < instanceCount; i++) { 2196144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt const Geometry& args = fGeoData[i]; 219776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2198bb2ff94e223014403f775c3532a25cc25b00c949brianosman GrColor color = args.fColor; 2199bb2ff94e223014403f775c3532a25cc25b00c949brianosman 220076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Compute the reciprocals of the radii here to save time in the shader 220176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar xRadRecip = SkScalarInvert(args.fXRadius); 220276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar yRadRecip = SkScalarInvert(args.fYRadius); 220376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar xInnerRadRecip = SkScalarInvert(args.fInnerXRadius); 220476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar yInnerRadRecip = SkScalarInvert(args.fInnerYRadius); 220576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 220676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt // Extend the radii out half a pixel to antialias. 220776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar xOuterRadius = args.fXRadius + SK_ScalarHalf; 220876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt SkScalar yOuterRadius = args.fYRadius + SK_ScalarHalf; 220976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2210bc227140ffea6eb15e2e8b147eb6d8ec6228d95aegdaniel const SkRect& bounds = args.fDevBounds; 221176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2212289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar yCoords[4] = {bounds.fTop, bounds.fTop + yOuterRadius, 2213289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bounds.fBottom - yOuterRadius, bounds.fBottom}; 2214289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar yOuterOffsets[4] = {yOuterRadius, 2215289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SK_ScalarNearlyZero, // we're using inversesqrt() in 2216289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // shader, so can't be exactly 0 2217289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SK_ScalarNearlyZero, yOuterRadius}; 221876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 221976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt for (int i = 0; i < 4; ++i) { 222076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); 2221bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 222276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); 222376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 222476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 222576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 222676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 222776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fLeft + xOuterRadius, yCoords[i]); 2228bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 222976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]); 223076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 223176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 223276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 223376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 223476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fRight - xOuterRadius, yCoords[i]); 2235bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 223676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]); 223776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 223876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 223976e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 224076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 224176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 2242bb2ff94e223014403f775c3532a25cc25b00c949brianosman verts->fColor = color; 224376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); 224476e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 224576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 224676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt verts++; 224776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 224876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 2249144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary helper.recordDraw(target, gp.get()); 225076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 225176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 225225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 2253289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon EllipticalRRectOp* that = t->cast<EllipticalRRectOp>(); 2254abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 2255abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 2256abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon that->bounds(), caps)) { 22578cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 22588cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 22598cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 2260cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (fStroked != that->fStroked) { 226176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 226276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 226376e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2264cdaa97bf664e0d584187efc125bfff670a064a9absalomon if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsingLocalCoords)) { 226576e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return false; 226676e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 226776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2268cdaa97bf664e0d584187efc125bfff670a064a9absalomon fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 226988cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 227076e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt return true; 227176e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt } 227276e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 22734b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon struct Geometry { 22744b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon GrColor fColor; 22754b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fXRadius; 22764b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fYRadius; 22774b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerXRadius; 22784b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkScalar fInnerYRadius; 22794b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkRect fDevBounds; 22804b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon }; 22814b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 2282289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool fStroked; 2283289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkMatrix fViewMatrixIfUsingLocalCoords; 2284289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkSTArray<1, Geometry, true> fGeoData; 22851b55a963a2374a14bb82eb887bb99ee91680f0ebreed 2286dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 228776e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt}; 228876e7fb6cbaa0994778cc4cf48bfe5e70bae59821joshualitt 2289649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstatic std::unique_ptr<GrMeshDrawOp> make_rrect_op(GrColor color, 2290649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon bool needsDistance, 2291649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 2292649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRRect& rrect, 2293649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke) { 22943e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt SkASSERT(viewMatrix.rectStaysRect()); 22953e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt SkASSERT(rrect.isSimple()); 22963e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt SkASSERT(!rrect.isOval()); 22973e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 229853e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon // RRect ops only handle simple, but not too simple, rrects. 229953e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon // Do any matrix crunching before we reset the draw state for device coords. 2300f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org const SkRect& rrectBounds = rrect.getBounds(); 2301d96a67bcb196aa4f73ff773bd45810a94ca872d8joshualitt SkRect bounds; 2302d96a67bcb196aa4f73ff773bd45810a94ca872d8joshualitt viewMatrix.mapRect(&bounds, rrectBounds); 2303f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 2304f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org SkVector radii = rrect.getSimpleRadii(); 2305289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX] * radii.fX + 2306289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon viewMatrix[SkMatrix::kMSkewY] * radii.fY); 2307289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX] * radii.fX + 2308289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon viewMatrix[SkMatrix::kMScaleY] * radii.fY); 23096bb3efc4db8e4e348c6ef6033ffaf8410a82eae5commit-bot@chromium.org 2310f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org SkStrokeRec::Style style = stroke.getStyle(); 2311f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 23124b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // Do (potentially) anisotropic mapping of stroke. Use -1s to indicate fill-only draws. 23134b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon SkVector scaledStroke = {-1, -1}; 2314f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org SkScalar strokeWidth = stroke.getWidth(); 2315f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 2316289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon bool isStrokeOnly = 2317289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style; 23180a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; 23190a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org 2320c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth bool isCircular = (xRadius == yRadius); 23210a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org if (hasStroke) { 23220a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org if (SkStrokeRec::kHairline_Style == style) { 23230a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org scaledStroke.set(1, 1); 23240a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org } else { 2325289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon scaledStroke.fX = SkScalarAbs( 2326289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon strokeWidth * (viewMatrix[SkMatrix::kMScaleX] + viewMatrix[SkMatrix::kMSkewY])); 2327289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon scaledStroke.fY = SkScalarAbs( 2328289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon strokeWidth * (viewMatrix[SkMatrix::kMSkewX] + viewMatrix[SkMatrix::kMScaleY])); 23290a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org } 23300a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org 2331c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth isCircular = isCircular && scaledStroke.fX == scaledStroke.fY; 2332c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // for non-circular rrects, if half of strokewidth is greater than radius, 2333c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth // we don't handle that right now 2334289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (!isCircular && (SK_ScalarHalf * scaledStroke.fX > xRadius || 2335289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon SK_ScalarHalf * scaledStroke.fY > yRadius)) { 233696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 23370a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org } 23380a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org } 23390a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org 23400a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org // The way the effect interpolates the offset-to-ellipse/circle-center attribute only works on 23410a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner rect of the nine- 23420a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org // patch will have fractional coverage. This only matters when the interior is actually filled. 23430a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org // We could consider falling back to rect rendering here, since a tiny radius is 23440a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org // indistinguishable from a square corner. 23450a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { 234696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2347f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } 2348f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org 2349f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org // if the corners are circles, use the circle renderer 2350c3d0e422761702c52a974411eaf0b06d223fe98ejvanverth if (isCircular) { 2351649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon return std::unique_ptr<GrMeshDrawOp>(new CircularRRectOp( 2352f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon color, needsDistance, viewMatrix, bounds, xRadius, scaledStroke.fX, isStrokeOnly)); 2353289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon // otherwise we use the ellipse renderer 2354f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } else { 2355289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return EllipticalRRectOp::Make(color, viewMatrix, bounds, xRadius, yRadius, scaledStroke, 2356289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon isStrokeOnly); 2357f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org } 23583e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt} 23593e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 2360649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstd::unique_ptr<GrMeshDrawOp> GrOvalOpFactory::MakeRRectOp(GrColor color, 2361649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon bool needsDistance, 2362649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 2363649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRRect& rrect, 2364649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke, 2365649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrShaderCaps* shaderCaps) { 23660cc2f85a19d50b45573d71d8c9d6ee1292c9fd3arobertphillips if (rrect.isOval()) { 2367289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return MakeOvalOp(color, viewMatrix, rrect.getBounds(), stroke, shaderCaps); 23683e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt } 23693e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 23700cc2f85a19d50b45573d71d8c9d6ee1292c9fd3arobertphillips if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { 23710cc2f85a19d50b45573d71d8c9d6ee1292c9fd3arobertphillips return nullptr; 23723e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt } 23733e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 2374289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return make_rrect_op(color, needsDistance, viewMatrix, rrect, stroke); 2375f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org} 23763e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 23774b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon/////////////////////////////////////////////////////////////////////////////// 23784b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 2379649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstd::unique_ptr<GrMeshDrawOp> GrOvalOpFactory::MakeOvalOp(GrColor color, 2380649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 2381649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRect& oval, 2382649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkStrokeRec& stroke, 2383649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrShaderCaps* shaderCaps) { 23844b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon // we can draw circles 23854f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar width = oval.width(); 23864f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (SkScalarNearlyEqual(width, oval.height()) && circle_stays_circle(viewMatrix)) { 23874f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkPoint center = {oval.centerX(), oval.centerY()}; 2388289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return CircleOp::Make(color, viewMatrix, center, width / 2.f, GrStyle(stroke, nullptr)); 23894b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 23904b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 2391eb868aa3a25e7b380e28ceffb45b89185af1afebStan Iliev // prefer the device space ellipse op for batchability 23924b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon if (viewMatrix.rectStaysRect()) { 2393289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return EllipseOp::Make(color, viewMatrix, oval, stroke); 23944b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon } 23954b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 2396eb868aa3a25e7b380e28ceffb45b89185af1afebStan Iliev // Otherwise, if we have shader derivative support, render as device-independent 2397eb868aa3a25e7b380e28ceffb45b89185af1afebStan Iliev if (shaderCaps->shaderDerivativeSupport()) { 2398eb868aa3a25e7b380e28ceffb45b89185af1afebStan Iliev return DIEllipseOp::Make(color, viewMatrix, oval, stroke); 2399eb868aa3a25e7b380e28ceffb45b89185af1afebStan Iliev } 2400eb868aa3a25e7b380e28ceffb45b89185af1afebStan Iliev 24014b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon return nullptr; 24024b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon} 24034b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon 24044b4a7cca638ce18b97399e40d158a7e9fb448d64bsalomon/////////////////////////////////////////////////////////////////////////////// 24053e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 2406649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomonstd::unique_ptr<GrMeshDrawOp> GrOvalOpFactory::MakeArcOp(GrColor color, const SkMatrix& viewMatrix, 2407649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkRect& oval, SkScalar startAngle, 2408649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkScalar sweepAngle, bool useCenter, 2409649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrStyle& style, 2410649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const GrShaderCaps* shaderCaps) { 241121af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon SkASSERT(!oval.isEmpty()); 241221af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon SkASSERT(sweepAngle); 24134f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar width = oval.width(); 241421af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon if (SkScalarAbs(sweepAngle) >= 360.f) { 241521af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon return nullptr; 241621af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon } 24174f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (!SkScalarNearlyEqual(width, oval.height()) || !circle_stays_circle(viewMatrix)) { 24184f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon return nullptr; 24194f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 24204f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkPoint center = {oval.centerX(), oval.centerY()}; 2421289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleOp::ArcParams arcParams = {SkDegreesToRadians(startAngle), SkDegreesToRadians(sweepAngle), 2422289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon useCenter}; 2423289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon return CircleOp::Make(color, viewMatrix, center, width / 2.f, style, &arcParams); 24244f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon} 24254f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 24264f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon/////////////////////////////////////////////////////////////////////////////// 24274f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon 24286f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 24293e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 24305ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(CircleOp) { 24314f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon do { 2432cadf75a8a41a11081af344c25601aad09099d0b4bsalomon SkScalar rotate = random->nextSScalar1() * 360.f; 2433cadf75a8a41a11081af344c25601aad09099d0b4bsalomon SkScalar translateX = random->nextSScalar1() * 1000.f; 2434cadf75a8a41a11081af344c25601aad09099d0b4bsalomon SkScalar translateY = random->nextSScalar1() * 1000.f; 2435cadf75a8a41a11081af344c25601aad09099d0b4bsalomon SkScalar scale = random->nextSScalar1() * 100.f; 2436cadf75a8a41a11081af344c25601aad09099d0b4bsalomon SkMatrix viewMatrix; 2437cadf75a8a41a11081af344c25601aad09099d0b4bsalomon viewMatrix.setRotate(rotate); 2438cadf75a8a41a11081af344c25601aad09099d0b4bsalomon viewMatrix.postTranslate(translateX, translateY); 2439cadf75a8a41a11081af344c25601aad09099d0b4bsalomon viewMatrix.postScale(scale, scale); 24404f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon GrColor color = GrRandomColor(random); 24414f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkRect circle = GrTest::TestSquare(random); 24424f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkPoint center = {circle.centerX(), circle.centerY()}; 24434f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkScalar radius = circle.width() / 2.f; 24444f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon SkStrokeRec stroke = GrTest::TestStrokeRec(random); 2445289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon CircleOp::ArcParams arcParamsTmp; 2446289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon const CircleOp::ArcParams* arcParams = nullptr; 24474f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon if (random->nextBool()) { 24484f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon arcParamsTmp.fStartAngleRadians = random->nextSScalar1() * SK_ScalarPI * 2; 244908197b22656c1b1200b0ac7b50e247b998a6db11robertphillips arcParamsTmp.fSweepAngleRadians = random->nextSScalar1() * SK_ScalarPI * 2 - .01f; 245008197b22656c1b1200b0ac7b50e247b998a6db11robertphillips arcParamsTmp.fUseCenter = random->nextBool(); 24514f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon arcParams = &arcParamsTmp; 24524f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 2453649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon std::unique_ptr<GrMeshDrawOp> op = CircleOp::Make(color, viewMatrix, center, radius, 2454649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon GrStyle(stroke, nullptr), arcParams); 2455289e3d8dd70b08b509aa29594fe831e0278304efBrian Salomon if (op) { 24565ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon return op; 24574f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } 24584f3a0ca85d28a8fc7fcc1ac5c4a1864c66bdea14bsalomon } while (true); 24593e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt} 24603e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 24615ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(EllipseOp) { 24623e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); 24633e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt GrColor color = GrRandomColor(random); 24646c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualitt SkRect ellipse = GrTest::TestSquare(random); 24655ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon return EllipseOp::Make(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random)); 24663e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt} 24673e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 24685ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(DIEllipseOp) { 24693e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt SkMatrix viewMatrix = GrTest::TestMatrix(random); 24703e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt GrColor color = GrRandomColor(random); 24716c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualitt SkRect ellipse = GrTest::TestSquare(random); 24725ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon return DIEllipseOp::Make(color, viewMatrix, ellipse, GrTest::TestStrokeRec(random)); 24733e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt} 24743e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 24755ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(RRectOp) { 24763e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); 24773e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt GrColor color = GrRandomColor(random); 24783e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt const SkRRect& rrect = GrTest::TestRRectSimple(random); 247979839d45f893ad5690fc83c951567b3686e781e6Robert Phillips bool needsDistance = random->nextBool(); 24805ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon return make_rrect_op(color, needsDistance, viewMatrix, rrect, GrTest::TestStrokeRec(random)); 24813e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt} 24823e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt 24833e708c53f79a04b588b6ca8e535e61f986d80b47joshualitt#endif 2484