11a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/* 21a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * Copyright 2015 Google Inc. 31a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * 41a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * Use of this source code is governed by a BSD-style license that can be 51a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas * found in the LICENSE file. 61a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas */ 71a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 81a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAALinearizingConvexPathRenderer.h" 91a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAAConvexTessellator.h" 101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrContext.h" 111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrDefaultGeoProcFactory.h" 125ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h" 131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrGeometryProcessor.h" 14742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h" 151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h" 16dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrProcessor.h" 176663acff010ce752e4bf778da81fa97448c9db31bsalomon#include "GrStyle.h" 181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h" 19dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "SkPathPriv.h" 201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkString.h" 211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkTraceEvent.h" 22e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h" 23895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h" 24b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon#include "ops/GrSimpleMeshDrawOpHelper.h" 251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 26bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const int DEFAULT_BUFFER_SIZE = 100; 27bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita 28bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For 29bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// the time being, we simply drop back to software rendering above this stroke width. 30bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kMaxStrokeWidth = 20.0; 311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasGrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() { 331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/////////////////////////////////////////////////////////////////////////////// 361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 375ed4423090e63e4c7888d6dd44fde177adea13f3Chris DaltonGrPathRenderer::CanDrawPath 385ed4423090e63e4c7888d6dd44fde177adea13f3Chris DaltonGrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { 390e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon if (GrAAType::kCoverage != args.fAAType) { 405ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 41bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 428acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (!args.fShape->knownToBeConvex()) { 435ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 44bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 458acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (args.fShape->style().pathEffect()) { 465ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 47bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 488acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (args.fShape->inverseFilled()) { 495ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 506663acff010ce752e4bf778da81fa97448c9db31bsalomon } 51a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman if (args.fShape->bounds().width() <= 0 && args.fShape->bounds().height() <= 0) { 52a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman // Stroked zero length lines should draw, but this PR doesn't handle that case 535ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 54a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman } 558acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 568c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 578c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (stroke.getStyle() == SkStrokeRec::kStroke_Style || 588c170971f182d47bc9af71fc88a607740d03dfd5robertphillips stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) { 59fea7763140ba74b78f2c30028452e250140b6f21ethannicholas if (!args.fViewMatrix->isSimilarity()) { 605ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 61fea7763140ba74b78f2c30028452e250140b6f21ethannicholas } 626663acff010ce752e4bf778da81fa97448c9db31bsalomon SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth(); 638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) { 645ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 665ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton if (strokeWidth > kMaxStrokeWidth || 675ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton !args.fShape->knownToBeClosed() || 685ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton stroke.getJoin() == SkPaint::Join::kRound_Join) { 695ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 705ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton } 715ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kYes; 725ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton } 735ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton if (stroke.getStyle() != SkStrokeRec::kFill_Style) { 745ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kNo; 75bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 765ed4423090e63e4c7888d6dd44fde177adea13f3Chris Dalton return CanDrawPath::kYes; 771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator 801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess, 811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas void* vertices, 821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride, 831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas GrColor color, 841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas uint16_t firstIndex, 851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas uint16_t* idxs, 861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas bool tweakAlphaForCoverage) { 871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas intptr_t verts = reinterpret_cast<intptr_t>(vertices); 881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numPts(); ++i) { 901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i); 911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // Make 'verts' point to the colors 941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas verts += sizeof(SkPoint); 951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numPts(); ++i) { 961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (tweakAlphaForCoverage) { 97bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255); 98bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i)); 991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); 1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; 1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } else { 1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; 103002c2ce66be69d41632c9603ce62c50f04156518mtklein *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 104bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita tess.coverage(i); 1051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 1081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numIndices(); ++i) { 1091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas idxs[i] = tess.index(i) + firstIndex; 1101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 1121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 11360fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomonstatic sk_sp<GrGeometryProcessor> create_lines_only_gp(bool tweakAlphaForCoverage, 11460fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomon const SkMatrix& viewMatrix, 11560fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomon bool usesLocalCoords) { 116df0c55785033c191d2d509c22662861588e4acd8joshualitt using namespace GrDefaultGeoProcFactory; 117df0c55785033c191d2d509c22662861588e4acd8joshualitt 118df0c55785033c191d2d509c22662861588e4acd8joshualitt Coverage::Type coverageType; 1198c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon if (tweakAlphaForCoverage) { 120df0c55785033c191d2d509c22662861588e4acd8joshualitt coverageType = Coverage::kSolid_Type; 121df0c55785033c191d2d509c22662861588e4acd8joshualitt } else { 122df0c55785033c191d2d509c22662861588e4acd8joshualitt coverageType = Coverage::kAttribute_Type; 1231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1248c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon LocalCoords::Type localCoordsType = 1258c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type; 1263de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType, 1273de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon viewMatrix); 1281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 1291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 130b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonnamespace { 1311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 132b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonclass AAFlatteningConvexPathOp final : public GrMeshDrawOp { 133b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate: 134b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon using Helper = GrSimpleMeshDrawOpHelperWithStencil; 1357c3e7180948766321c51d165737555e78910de51Brian Salomon 136b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonpublic: 137b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon DEFINE_OP_CLASS_ID 138b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, 139b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const SkMatrix& viewMatrix, 140b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const SkPath& path, 141b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkScalar strokeWidth, 142b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkStrokeRec::Style style, 143b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkPaint::Join join, 144b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkScalar miterLimit, 145b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings) { 146b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return Helper::FactoryHelper<AAFlatteningConvexPathOp>(std::move(paint), viewMatrix, path, 147b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon strokeWidth, style, join, miterLimit, 148b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon stencilSettings); 1497c3e7180948766321c51d165737555e78910de51Brian Salomon } 1501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 151b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon AAFlatteningConvexPathOp(const Helper::MakeArgs& helperArgs, 152b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon GrColor color, 153780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix, 154780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkPath& path, 155780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar strokeWidth, 156780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkStrokeRec::Style style, 157780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkPaint::Join join, 158b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkScalar miterLimit, 159b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings) 160b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) { 161780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.emplace_back( 162780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit}); 163780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon 164780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // compute bounds 165780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkRect bounds = path.getBounds(); 166780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar w = strokeWidth; 167780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon if (w > 0) { 168780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon w /= 2; 169780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // If the half stroke width is < 1 then we effectively fallback to bevel joins. 170780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon if (SkPaint::kMiter_Join == join && w > 1.f) { 171780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon w *= miterLimit; 172780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 173780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bounds.outset(w, w); 174780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 175780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo); 176780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 177780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon 178b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const char* name() const override { return "AAFlatteningConvexPathOp"; } 179b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 180f1748f5a9238a0d3e189d50fc5e57ae8b8ec087cRobert Phillips void visitProxies(const VisitProxyFunc& func) const override { 181b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips fHelper.visitProxies(func); 182b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips } 183b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips 184b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkString dumpInfo() const override { 185b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkString string; 186b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon for (const auto& path : fPaths) { 187b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string.appendf( 188b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, " 189b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon "MiterLimit: %.2f\n", 190b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit); 191b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon } 192b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string += fHelper.dumpInfo(); 193b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string += INHERITED::dumpInfo(); 194b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return string; 19592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 19692aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 197b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); } 198b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 1999a725dd9485654155e2e4196c32d372360bcdb61Brian Osman RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip, 2009a725dd9485654155e2e4196c32d372360bcdb61Brian Osman GrPixelConfigIsClamped dstIsClamped) override { 2019a725dd9485654155e2e4196c32d372360bcdb61Brian Osman return fHelper.xpRequiresDstTexture(caps, clip, dstIsClamped, 2029a725dd9485654155e2e4196c32d372360bcdb61Brian Osman GrProcessorAnalysisCoverage::kSingleChannel, 203b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon &fPaths.back().fColor); 2041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 206b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate: 207b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp, 208b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrPipeline* pipeline, int vertexCount, size_t vertexStride, void* vertices, 209b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon int indexCount, uint16_t* indices) const { 2101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount == 0 || indexCount == 0) { 2111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 213ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton const GrBuffer* vertexBuffer; 2143809bab7ed344ad140346c38e149dabf10bd525fChris Dalton GrMesh mesh(GrPrimitiveType::kTriangles); 215bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton int firstVertex; 216002c2ce66be69d41632c9603ce62c50f04156518mtklein void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, 217bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton &firstVertex); 2181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!verts) { 2191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate vertices\n"); 2201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(verts, vertices, vertexCount * vertexStride); 2231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 224397536cabe12a9936659870dd220c869789424bacdalton const GrBuffer* indexBuffer; 225bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton int firstIndex; 226bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); 2271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!idxs) { 2281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate indices\n"); 2291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2301a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(idxs, indices, indexCount * sizeof(uint16_t)); 232114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1); 233114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setVertexData(vertexBuffer, firstVertex); 234b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon target->draw(gp, pipeline, mesh); 2351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 236002c2ce66be69d41632c9603ce62c50f04156518mtklein 23791326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon void onPrepareDraws(Target* target) override { 238b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrPipeline* pipeline = fHelper.makePipeline(target); 2391a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 240df0c55785033c191d2d509c22662861588e4acd8joshualitt // Setup GrGeometryProcessor 241b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(fHelper.compatibleWithAlphaAsCoverage(), 242b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->viewMatrix(), 243b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon fHelper.usesLocalCoords())); 244df0c55785033c191d2d509c22662861588e4acd8joshualitt if (!gp) { 245df0c55785033c191d2d509c22662861588e4acd8joshualitt SkDebugf("Couldn't create a GrGeometryProcessor\n"); 2461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride = gp->getVertexStride(); 2501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 251b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkASSERT(fHelper.compatibleWithAlphaAsCoverage() 252b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) 253b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon : vertexStride == 254b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); 2551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 256780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon int instanceCount = fPaths.count(); 2571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int vertexCount = 0; 2591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int indexCount = 0; 2601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxVertices = DEFAULT_BUFFER_SIZE; 2611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxIndices = DEFAULT_BUFFER_SIZE; 262002c2ce66be69d41632c9603ce62c50f04156518mtklein uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride); 263002c2ce66be69d41632c9603ce62c50f04156518mtklein uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t)); 2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < instanceCount; i++) { 265780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const PathData& args = fPaths[i]; 2668c170971f182d47bc9af71fc88a607740d03dfd5robertphillips GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth, 2678c170971f182d47bc9af71fc88a607740d03dfd5robertphillips args.fJoin, args.fMiterLimit); 2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!tess.tessellate(args.fViewMatrix, args.fPath)) { 2701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas continue; 2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentIndices = tess.numIndices(); 2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > UINT16_MAX) { 275002c2ce66be69d41632c9603ce62c50f04156518mtklein // if we added the current instance, we would overflow the indices we can store in a 2761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // uint16_t. Draw what we've got so far and reset. 277b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, 278b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon indexCount, indices); 2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount = 0; 2801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount = 0; 2811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentVertices = tess.numPts(); 2831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount + currentVertices > maxVertices) { 2841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2); 285002c2ce66be69d41632c9603ce62c50f04156518mtklein vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride); 2861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > maxIndices) { 2881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2); 289002c2ce66be69d41632c9603ce62c50f04156518mtklein indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t)); 2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 292002c2ce66be69d41632c9603ce62c50f04156518mtklein extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor, 293b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon vertexCount, indices + indexCount, 294b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon fHelper.compatibleWithAlphaAsCoverage()); 2951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount += currentVertices; 2961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount += currentIndices; 2971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 298b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, 299b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon indices); 300002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(vertices); 301002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(indices); 3021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 3031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 30425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 305780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>(); 306b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { 3078cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 3088cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 3098cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 310780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin()); 31188cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 3121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 3141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 315780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; } 3161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 317780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon struct PathData { 3180432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon GrColor fColor; 3190432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkMatrix fViewMatrix; 3200432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath fPath; 3210432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fStrokeWidth; 3228c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style fStyle; 3230432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join fJoin; 3240432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fMiterLimit; 3250432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon }; 3260432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon 327780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkSTArray<1, PathData, true> fPaths; 328b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon Helper fHelper; 3291b55a963a2374a14bb82eb887bb99ee91680f0ebreed 330b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon typedef GrMeshDrawOp INHERITED; 3311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}; 3321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 333b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon} // anonymous namespace 334b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 3350aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { 3361105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), 337de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt "GrAALinearizingConvexPathRenderer::onDrawPath"); 3387c8460e10135c05a42d0744b84838bbc24398ac2Brian Salomon SkASSERT(GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType()); 3398acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon SkASSERT(!args.fShape->isEmpty()); 3408c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkASSERT(!args.fShape->style().pathEffect()); 341ecbc12b1c1c72de0cf7bba4a3f6a7cce4f43bf41csmartdalton 3420432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path; 3430432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon args.fShape->asPath(&path); 3448acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon bool fill = args.fShape->style().isSimpleFill(); 3458acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 3460432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth(); 3470432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin(); 3480432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = stroke.getMiter(); 3491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 350b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make( 351b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth, stroke.getStyle(), join, 352b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon miterLimit, args.fUserStencilSettings); 353b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); 3541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3561a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/////////////////////////////////////////////////////////////////////////////////////////////////// 3581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3596f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 3601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 361b295573c93e7a9a78ee736a399c256d7669b79beBrian SalomonGR_DRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) { 362780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random); 3630432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path = GrTest::TestPathConvex(random); 3648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style, 36660c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby SkStrokeRec::kStroke_Style, 3678c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::kStrokeAndFill_Style }; 3688c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3698c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style style = styles[random->nextU() % 3]; 3708c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3718c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkScalar strokeWidth = -1.f; 3720432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = SkPaint::kMiter_Join; 3730432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = 0.5f; 3748c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3758c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (SkStrokeRec::kFill_Style != style) { 3768c170971f182d47bc9af71fc88a607740d03dfd5robertphillips strokeWidth = random->nextRangeF(1.0f, 10.0f); 3778c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (random->nextBool()) { 3788c170971f182d47bc9af71fc88a607740d03dfd5robertphillips join = SkPaint::kMiter_Join; 3798c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } else { 3808c170971f182d47bc9af71fc88a607740d03dfd5robertphillips join = SkPaint::kBevel_Join; 3818c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 3828c170971f182d47bc9af71fc88a607740d03dfd5robertphillips miterLimit = random->nextRangeF(0.5f, 2.0f); 3838c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 384b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context); 385b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return AAFlatteningConvexPathOp::Make(std::move(paint), viewMatrix, path, strokeWidth, style, 386b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon join, miterLimit, stencilSettings); 3871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif 390