GrAALinearizingConvexPathRenderer.cpp revision 91326c34ee1f1531d62caa153746821b58e6e55d
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 370aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { 380e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon if (GrAAType::kCoverage != args.fAAType) { 39bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita return false; 40bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 418acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (!args.fShape->knownToBeConvex()) { 42bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita return false; 43bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 448acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (args.fShape->style().pathEffect()) { 45bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita return false; 46bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 478acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (args.fShape->inverseFilled()) { 486663acff010ce752e4bf778da81fa97448c9db31bsalomon return false; 496663acff010ce752e4bf778da81fa97448c9db31bsalomon } 50a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman if (args.fShape->bounds().width() <= 0 && args.fShape->bounds().height() <= 0) { 51a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman // Stroked zero length lines should draw, but this PR doesn't handle that case 52a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman return false; 53a98e399ba5aa6261f60e18c627777eec35b7b147Brian Osman } 548acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 558c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 568c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (stroke.getStyle() == SkStrokeRec::kStroke_Style || 578c170971f182d47bc9af71fc88a607740d03dfd5robertphillips stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) { 58fea7763140ba74b78f2c30028452e250140b6f21ethannicholas if (!args.fViewMatrix->isSimilarity()) { 59fea7763140ba74b78f2c30028452e250140b6f21ethannicholas return false; 60fea7763140ba74b78f2c30028452e250140b6f21ethannicholas } 616663acff010ce752e4bf778da81fa97448c9db31bsalomon SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth(); 628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) { 638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips return false; 648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips return strokeWidth <= kMaxStrokeWidth && 668acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon args.fShape->knownToBeClosed() && 676663acff010ce752e4bf778da81fa97448c9db31bsalomon stroke.getJoin() != SkPaint::Join::kRound_Join; 68bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 696663acff010ce752e4bf778da81fa97448c9db31bsalomon return stroke.getStyle() == SkStrokeRec::kFill_Style; 701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator 731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess, 741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas void* vertices, 751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride, 761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas GrColor color, 771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas uint16_t firstIndex, 781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas uint16_t* idxs, 791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas bool tweakAlphaForCoverage) { 801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas intptr_t verts = reinterpret_cast<intptr_t>(vertices); 811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numPts(); ++i) { 831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i); 841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // Make 'verts' point to the colors 871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas verts += sizeof(SkPoint); 881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numPts(); ++i) { 891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (tweakAlphaForCoverage) { 90bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255); 91bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i)); 921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); 931a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; 941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } else { 951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; 96002c2ce66be69d41632c9603ce62c50f04156518mtklein *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 97bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita tess.coverage(i); 981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numIndices(); ++i) { 1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas idxs[i] = tess.index(i) + firstIndex; 1031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 1051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 10660fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomonstatic sk_sp<GrGeometryProcessor> create_lines_only_gp(bool tweakAlphaForCoverage, 10760fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomon const SkMatrix& viewMatrix, 10860fb0b2548c7f03b58fc52aa298b07ed137c84e3Brian Salomon bool usesLocalCoords) { 109df0c55785033c191d2d509c22662861588e4acd8joshualitt using namespace GrDefaultGeoProcFactory; 110df0c55785033c191d2d509c22662861588e4acd8joshualitt 111df0c55785033c191d2d509c22662861588e4acd8joshualitt Coverage::Type coverageType; 1128c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon if (tweakAlphaForCoverage) { 113df0c55785033c191d2d509c22662861588e4acd8joshualitt coverageType = Coverage::kSolid_Type; 114df0c55785033c191d2d509c22662861588e4acd8joshualitt } else { 115df0c55785033c191d2d509c22662861588e4acd8joshualitt coverageType = Coverage::kAttribute_Type; 1161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1178c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon LocalCoords::Type localCoordsType = 1188c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type; 1193de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType, 1203de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon viewMatrix); 1211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 1221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 123b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonnamespace { 1241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 125b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonclass AAFlatteningConvexPathOp final : public GrMeshDrawOp { 126b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate: 127b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon using Helper = GrSimpleMeshDrawOpHelperWithStencil; 1287c3e7180948766321c51d165737555e78910de51Brian Salomon 129b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonpublic: 130b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon DEFINE_OP_CLASS_ID 131b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, 132b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const SkMatrix& viewMatrix, 133b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const SkPath& path, 134b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkScalar strokeWidth, 135b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkStrokeRec::Style style, 136b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkPaint::Join join, 137b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkScalar miterLimit, 138b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings) { 139b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return Helper::FactoryHelper<AAFlatteningConvexPathOp>(std::move(paint), viewMatrix, path, 140b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon strokeWidth, style, join, miterLimit, 141b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon stencilSettings); 1427c3e7180948766321c51d165737555e78910de51Brian Salomon } 1431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 144b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon AAFlatteningConvexPathOp(const Helper::MakeArgs& helperArgs, 145b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon GrColor color, 146780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix, 147780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkPath& path, 148780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar strokeWidth, 149780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkStrokeRec::Style style, 150780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkPaint::Join join, 151b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkScalar miterLimit, 152b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings) 153b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon : INHERITED(ClassID()), fHelper(helperArgs, GrAAType::kCoverage, stencilSettings) { 154780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.emplace_back( 155780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit}); 156780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon 157780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // compute bounds 158780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkRect bounds = path.getBounds(); 159780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar w = strokeWidth; 160780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon if (w > 0) { 161780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon w /= 2; 162780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // If the half stroke width is < 1 then we effectively fallback to bevel joins. 163780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon if (SkPaint::kMiter_Join == join && w > 1.f) { 164780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon w *= miterLimit; 165780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 166780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bounds.outset(w, w); 167780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 168780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo); 169780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 170780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon 171b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const char* name() const override { return "AAFlatteningConvexPathOp"; } 172b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 173b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkString dumpInfo() const override { 174b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkString string; 175b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon for (const auto& path : fPaths) { 176b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string.appendf( 177b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, " 178b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon "MiterLimit: %.2f\n", 179b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit); 180b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon } 181b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string += fHelper.dumpInfo(); 182b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon string += INHERITED::dumpInfo(); 183b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return string; 18492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 18592aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 186b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon FixedFunctionFlags fixedFunctionFlags() const override { return fHelper.fixedFunctionFlags(); } 187b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 188b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override { 189b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return fHelper.xpRequiresDstTexture(caps, clip, GrProcessorAnalysisCoverage::kSingleChannel, 190b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon &fPaths.back().fColor); 1911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 193b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomonprivate: 194b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp, 195b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrPipeline* pipeline, int vertexCount, size_t vertexStride, void* vertices, 196b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon int indexCount, uint16_t* indices) const { 1971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount == 0 || indexCount == 0) { 1981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 1991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 200ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton const GrBuffer* vertexBuffer; 2013809bab7ed344ad140346c38e149dabf10bd525fChris Dalton GrMesh mesh(GrPrimitiveType::kTriangles); 202bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton int firstVertex; 203002c2ce66be69d41632c9603ce62c50f04156518mtklein void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, 204bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton &firstVertex); 2051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!verts) { 2061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate vertices\n"); 2071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(verts, vertices, vertexCount * vertexStride); 2101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 211397536cabe12a9936659870dd220c869789424bacdalton const GrBuffer* indexBuffer; 212bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton int firstIndex; 213bca46e29e9f96999df0b38fb9359e71b73217c94Chris Dalton uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); 2141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!idxs) { 2151a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate indices\n"); 2161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(idxs, indices, indexCount * sizeof(uint16_t)); 219114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setIndexed(indexBuffer, indexCount, firstIndex, 0, vertexCount - 1); 220114a3c0b2b26c84b9d0907a99fd8ab7938631246Chris Dalton mesh.setVertexData(vertexBuffer, firstVertex); 221b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon target->draw(gp, pipeline, mesh); 2221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 223002c2ce66be69d41632c9603ce62c50f04156518mtklein 22491326c34ee1f1531d62caa153746821b58e6e55dBrian Salomon void onPrepareDraws(Target* target) override { 225b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrPipeline* pipeline = fHelper.makePipeline(target); 2261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 227df0c55785033c191d2d509c22662861588e4acd8joshualitt // Setup GrGeometryProcessor 228b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon sk_sp<GrGeometryProcessor> gp(create_lines_only_gp(fHelper.compatibleWithAlphaAsCoverage(), 229b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->viewMatrix(), 230b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon fHelper.usesLocalCoords())); 231df0c55785033c191d2d509c22662861588e4acd8joshualitt if (!gp) { 232df0c55785033c191d2d509c22662861588e4acd8joshualitt SkDebugf("Couldn't create a GrGeometryProcessor\n"); 2331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride = gp->getVertexStride(); 2371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 238b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon SkASSERT(fHelper.compatibleWithAlphaAsCoverage() 239b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) 240b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon : vertexStride == 241b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); 2421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 243780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon int instanceCount = fPaths.count(); 2441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int vertexCount = 0; 2461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int indexCount = 0; 2471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxVertices = DEFAULT_BUFFER_SIZE; 2481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxIndices = DEFAULT_BUFFER_SIZE; 249002c2ce66be69d41632c9603ce62c50f04156518mtklein uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride); 250002c2ce66be69d41632c9603ce62c50f04156518mtklein uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t)); 2511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < instanceCount; i++) { 252780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const PathData& args = fPaths[i]; 2538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth, 2548c170971f182d47bc9af71fc88a607740d03dfd5robertphillips args.fJoin, args.fMiterLimit); 2551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2561a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!tess.tessellate(args.fViewMatrix, args.fPath)) { 2571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas continue; 2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentIndices = tess.numIndices(); 2611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkASSERT(currentIndices <= UINT16_MAX); 2621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > UINT16_MAX) { 263002c2ce66be69d41632c9603ce62c50f04156518mtklein // if we added the current instance, we would overflow the indices we can store in a 2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // uint16_t. Draw what we've got so far and reset. 265b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, 266b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon indexCount, indices); 2671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount = 0; 2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount = 0; 2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentVertices = tess.numPts(); 2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount + currentVertices > maxVertices) { 2721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2); 273002c2ce66be69d41632c9603ce62c50f04156518mtklein vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride); 2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > maxIndices) { 2761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2); 277002c2ce66be69d41632c9603ce62c50f04156518mtklein indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t)); 2781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 280002c2ce66be69d41632c9603ce62c50f04156518mtklein extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor, 281b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon vertexCount, indices + indexCount, 282b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon fHelper.compatibleWithAlphaAsCoverage()); 2831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount += currentVertices; 2841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount += currentIndices; 2851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 286b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, 287b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon indices); 288002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(vertices); 289002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(indices); 2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 29225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 293780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>(); 294b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { 2958cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 2968cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 2978cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 298780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin()); 29988cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 3001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 3021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 303780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; } 3041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 305780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon struct PathData { 3060432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon GrColor fColor; 3070432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkMatrix fViewMatrix; 3080432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath fPath; 3090432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fStrokeWidth; 3108c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style fStyle; 3110432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join fJoin; 3120432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fMiterLimit; 3130432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon }; 3140432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon 315780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkSTArray<1, PathData, true> fPaths; 316b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon Helper fHelper; 3171b55a963a2374a14bb82eb887bb99ee91680f0ebreed 318b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon typedef GrMeshDrawOp INHERITED; 3191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}; 3201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 321b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon} // anonymous namespace 322b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon 3230aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { 3241105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), 325de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt "GrAALinearizingConvexPathRenderer::onDrawPath"); 3267c8460e10135c05a42d0744b84838bbc24398ac2Brian Salomon SkASSERT(GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType()); 3278acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon SkASSERT(!args.fShape->isEmpty()); 3288c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkASSERT(!args.fShape->style().pathEffect()); 329ecbc12b1c1c72de0cf7bba4a3f6a7cce4f43bf41csmartdalton 3300432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path; 3310432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon args.fShape->asPath(&path); 3328acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon bool fill = args.fShape->style().isSimpleFill(); 3338acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 3340432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth(); 3350432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin(); 3360432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = stroke.getMiter(); 3371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 338b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make( 339b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth, stroke.getStyle(), join, 340b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon miterLimit, args.fUserStencilSettings); 341b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op)); 3421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3431a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/////////////////////////////////////////////////////////////////////////////////////////////////// 3461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3476f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 3481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 349b295573c93e7a9a78ee736a399c256d7669b79beBrian SalomonGR_DRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) { 350780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random); 3510432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path = GrTest::TestPathConvex(random); 3528c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style styles[3] = { SkStrokeRec::kFill_Style, 35460c05f98aa22d89e4ef25acb4799936f5df3cff2Herb Derby SkStrokeRec::kStroke_Style, 3558c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::kStrokeAndFill_Style }; 3568c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3578c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style style = styles[random->nextU() % 3]; 3588c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkScalar strokeWidth = -1.f; 3600432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = SkPaint::kMiter_Join; 3610432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = 0.5f; 3628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 3638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (SkStrokeRec::kFill_Style != style) { 3648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips strokeWidth = random->nextRangeF(1.0f, 10.0f); 3658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (random->nextBool()) { 3668c170971f182d47bc9af71fc88a607740d03dfd5robertphillips join = SkPaint::kMiter_Join; 3678c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } else { 3688c170971f182d47bc9af71fc88a607740d03dfd5robertphillips join = SkPaint::kBevel_Join; 3698c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 3708c170971f182d47bc9af71fc88a607740d03dfd5robertphillips miterLimit = random->nextRangeF(0.5f, 2.0f); 3718c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 372b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon const GrUserStencilSettings* stencilSettings = GrGetRandomStencil(random, context); 373b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon return AAFlatteningConvexPathOp::Make(std::move(paint), viewMatrix, path, strokeWidth, style, 374b295573c93e7a9a78ee736a399c256d7669b79beBrian Salomon join, miterLimit, stencilSettings); 3751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif 378