GrAALinearizingConvexPathRenderer.cpp revision 5ed4423090e63e4c7888d6dd44fde177adea13f3
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 180b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkString dumpInfo() const override { 181b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkString string; 182b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon for (const auto& path : fPaths) { 183b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string.appendf( 184b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, " 185b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon "MiterLimit: %.2f\n", 186b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit); 187b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon } 188b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string += fHelper.dumpInfo(); 189b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string += INHERITED::dumpInfo(); 190b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return string; 19192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 19292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 193b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); } 194b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 195b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override { 196b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel, 197b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon &fPaths.back().fColor); 1981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 200b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate: 201b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp, 202b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrPipeline* pipeline, int vertexCount, size_t vertexStride, void* vertices, 203b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon int indexCount, uint16_t* indices) const { 2041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount == 0 || indexCount == 0) { 2051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 207ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton const GrBuffer* vertexBuffer; 2083809bab7ed344ad140346c38e149dabf10bd525fChris Dalton GrMesh mesh(GrPrimitiveType::kTriangles); 209bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton int firstVertex; 210002c2ce66be69d41632c9603ce62c50f04156518mtklein void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, 211bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton &firstVertex); 2121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!verts) { 2131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate vertices\n"); 2141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(verts, vertices, vertexCount * vertexStride); 2171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 218397536cabe12a9936659870dd220c869789424bacdalton const GrBuffer* indexBuffer; 219bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton int firstIndex; 220bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); 2211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!idxs) { 2221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate indices\n"); 2231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(idxs, indices, indexCount * sizeof(uint16_t)); 226114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1); 227114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setVertexData(vertexBuffer, firstVertex); 228b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon target->draw(gp, pipeline, mesh); 2291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 230002c2ce66be69d41632c9603ce62c50f04156518mtklein 23191326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon void onPrepareDraws(Target* target) override { 232b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrPipeline* pipeline = fHelper.makePipeline(target); 2331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 234df0c55785033c191d2d509c22662861588e4acd8joshualitt // Setup GrGeometryProcessor 235b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(fHelper.compatibleWithAlphaAsCoverage(), 236b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->viewMatrix(), 237b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon fHelper.usesLocalCoords())); 238df0c55785033c191d2d509c22662861588e4acd8joshualitt if (!gp) { 239df0c55785033c191d2d509c22662861588e4acd8joshualitt SkDebugf("Couldn't create a GrGeometryProcessor\n"); 2401a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2411a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride = gp->getVertexStride(); 2441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 245b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkASSERT(fHelper.compatibleWithAlphaAsCoverage() 246b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) 247b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon : vertexStride == 248b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); 2491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 250780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon int instanceCount = fPaths.count(); 2511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int vertexCount = 0; 2531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int indexCount = 0; 2541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxVertices = DEFAULT_BUFFER_SIZE; 2551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxIndices = DEFAULT_BUFFER_SIZE; 256002c2ce66be69d41632c9603ce62c50f04156518mtklein uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride); 257002c2ce66be69d41632c9603ce62c50f04156518mtklein uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t)); 2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < instanceCount; i++) { 259780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const PathData& args = fPaths[i]; 2608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth, 2618c170971f182d47bc9af71fc88a607740d03dfd5robertphillips args.fJoin, args.fMiterLimit); 2621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2631a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!tess.tessellate(args.fViewMatrix, args.fPath)) { 2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas continue; 2651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentIndices = tess.numIndices(); 2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkASSERT(currentIndices <= UINT16_MAX); 2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > UINT16_MAX) { 270002c2ce66be69d41632c9603ce62c50f04156518mtklein // if we added the current instance, we would overflow the indices we can store in a 2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // uint16_t. Draw what we've got so far and reset. 272b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, 273b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon indexCount, indices); 2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount = 0; 2751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount = 0; 2761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentVertices = tess.numPts(); 2781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount + currentVertices > maxVertices) { 2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2); 280002c2ce66be69d41632c9603ce62c50f04156518mtklein vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride); 2811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > maxIndices) { 2831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2); 284002c2ce66be69d41632c9603ce62c50f04156518mtklein indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t)); 2851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 287002c2ce66be69d41632c9603ce62c50f04156518mtklein extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor, 288b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon vertexCount, indices + indexCount, 289b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon fHelper.compatibleWithAlphaAsCoverage()); 2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount += currentVertices; 2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount += currentIndices; 2921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 293b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, 294b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon indices); 295002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(vertices); 296002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(indices); 2971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 29925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 300780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>(); 301b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { 3028cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 3038cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 3048cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 305780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin()); 30688cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 3071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 3091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 310780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; } 3111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 312780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon struct PathData { 3130432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon GrColor fColor; 3140432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkMatrix fViewMatrix; 3150432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath fPath; 3160432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fStrokeWidth; 3178c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style fStyle; 3180432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join fJoin; 3190432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fMiterLimit; 3200432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon }; 3210432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon 322780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkSTArray<1, PathData, true> fPaths; 323b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon Helper fHelper; 3241b55a963a2374a14bb82eb887bb99ee91680f0ebreed 325b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon typedef GrMeshDrawOp INHERITED; 3261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}; 3271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 328b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon} // anonymous namespace 329b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 3300aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { 3311105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), 332de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt "GrAALinearizingConvexPathRenderer::onDrawPath"); 3337c8460e10135c05a42d0744b84838bbc24398ac2Brian Salomon SkASSERT(GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType()); 3348acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon SkASSERT(!args.fShape->isEmpty()); 3358c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkASSERT(!args.fShape->style().pathEffect()); 336ecbc12b1c1c72de0cf7bba4a3f6a7cce4f43bf41csmartdalton 3370432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path; 3380432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon args.fShape->asPath(&path); 3398acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon bool fill = args.fShape->style().isSimpleFill(); 3408acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 3410432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth(); 3420432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin(); 3430432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = stroke.getMiter(); 3441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 345b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make( 346b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth, stroke.getStyle(), join, 347b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon miterLimit, args.fUserStencilSettings); 348b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); 3491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/////////////////////////////////////////////////////////////////////////////////////////////////// 3531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3546f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 3551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 356b295573c93e7a9a78ee736a399c256d7669b79beBrian SalomonGR_DRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) { 357780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random); 3580432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path = GrTest::TestPathConvex(random); 3598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style, 36160c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby SkStrokeRec::kStroke_Style, 3628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::kStrokeAndFill_Style }; 3638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style style = styles[random->nextU() % 3]; 3658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3668c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkScalar strokeWidth = -1.f; 3670432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = SkPaint::kMiter_Join; 3680432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = 0.5f; 3698c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3708c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (SkStrokeRec::kFill_Style != style) { 3718c170971f182d47bc9af71fc88a607740d03dfd5robertphillips strokeWidth = random->nextRangeF(1.0f, 10.0f); 3728c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (random->nextBool()) { 3738c170971f182d47bc9af71fc88a607740d03dfd5robertphillips join = SkPaint::kMiter_Join; 3748c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } else { 3758c170971f182d47bc9af71fc88a607740d03dfd5robertphillips join = SkPaint::kBevel_Join; 3768c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 3778c170971f182d47bc9af71fc88a607740d03dfd5robertphillips miterLimit = random->nextRangeF(0.5f, 2.0f); 3788c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 379b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context); 380b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return AAFlatteningConvexPathOp::Make(std::move(paint), viewMatrix, path, strokeWidth, style, 381b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon join, miterLimit, stencilSettings); 3821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif 385