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 101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrAAConvexTessellator.h" 111a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrContext.h" 121a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrDefaultGeoProcFactory.h" 135ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon#include "GrDrawOpTest.h" 141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrGeometryProcessor.h" 15742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h" 161a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h" 17bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon#include "GrPipelineBuilder.h" 18dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "GrProcessor.h" 196663acff010ce752e4bf778da81fa97448c9db31bsalomon#include "GrStyle.h" 201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h" 21dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon#include "SkPathPriv.h" 221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkString.h" 231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkTraceEvent.h" 24e659a581f63fdccb64dce2dc8a478cf56831feeaegdaniel#include "glsl/GrGLSLGeometryProcessor.h" 25895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrMeshDrawOp.h" 261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 27bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const int DEFAULT_BUFFER_SIZE = 100; 28bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita 29bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// The thicker the stroke, the harder it is to produce high-quality results using tessellation. For 30bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// the time being, we simply drop back to software rendering above this stroke width. 31bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kMaxStrokeWidth = 20.0; 321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasGrAALinearizingConvexPathRenderer::GrAALinearizingConvexPathRenderer() { 341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/////////////////////////////////////////////////////////////////////////////// 371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 380aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { 390e8fc8b9e6a138cf4a66b421fb824679df717329Brian Salomon if (GrAAType::kCoverage != args.fAAType) { 40bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita return false; 41bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 428acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (!args.fShape->knownToBeConvex()) { 43bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita return false; 44bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 458acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (args.fShape->style().pathEffect()) { 46bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita return false; 47bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 488acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon if (args.fShape->inverseFilled()) { 496663acff010ce752e4bf778da81fa97448c9db31bsalomon return false; 506663acff010ce752e4bf778da81fa97448c9db31bsalomon } 518acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 528c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (stroke.getStyle() == SkStrokeRec::kStroke_Style || 548c170971f182d47bc9af71fc88a607740d03dfd5robertphillips stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style) { 55fea7763140ba74b78f2c30028452e250140b6f21ethannicholas if (!args.fViewMatrix->isSimilarity()) { 56fea7763140ba74b78f2c30028452e250140b6f21ethannicholas return false; 57fea7763140ba74b78f2c30028452e250140b6f21ethannicholas } 586663acff010ce752e4bf778da81fa97448c9db31bsalomon SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth(); 598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips if (strokeWidth < 1.0f && stroke.getStyle() == SkStrokeRec::kStroke_Style) { 608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips return false; 618c170971f182d47bc9af71fc88a607740d03dfd5robertphillips } 628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips return strokeWidth <= kMaxStrokeWidth && 638acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon args.fShape->knownToBeClosed() && 646663acff010ce752e4bf778da81fa97448c9db31bsalomon stroke.getJoin() != SkPaint::Join::kRound_Join; 65bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita } 666663acff010ce752e4bf778da81fa97448c9db31bsalomon return stroke.getStyle() == SkStrokeRec::kFill_Style; 671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// extract the result vertices and indices from the GrAAConvexTessellator 701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasstatic void extract_verts(const GrAAConvexTessellator& tess, 711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas void* vertices, 721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride, 731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas GrColor color, 741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas uint16_t firstIndex, 751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas uint16_t* idxs, 761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas bool tweakAlphaForCoverage) { 771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas intptr_t verts = reinterpret_cast<intptr_t>(vertices); 781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numPts(); ++i) { 801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *((SkPoint*)((intptr_t)verts + i * vertexStride)) = tess.point(i); 811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // Make 'verts' point to the colors 841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas verts += sizeof(SkPoint); 851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numPts(); ++i) { 861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (tweakAlphaForCoverage) { 87bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255); 88bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i)); 891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); 901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; 911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } else { 921a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; 93002c2ce66be69d41632c9603ce62c50f04156518mtklein *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor)) = 94bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita tess.coverage(i); 951a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < tess.numIndices(); ++i) { 991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas idxs[i] = tess.index(i) + firstIndex; 1001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 1021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 10306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemanstatic sk_sp<GrGeometryProcessor> create_fill_gp(bool tweakAlphaForCoverage, 104df0c55785033c191d2d509c22662861588e4acd8joshualitt const SkMatrix& viewMatrix, 1058c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon bool usesLocalCoords) { 106df0c55785033c191d2d509c22662861588e4acd8joshualitt using namespace GrDefaultGeoProcFactory; 107df0c55785033c191d2d509c22662861588e4acd8joshualitt 108df0c55785033c191d2d509c22662861588e4acd8joshualitt Coverage::Type coverageType; 1098c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon if (tweakAlphaForCoverage) { 110df0c55785033c191d2d509c22662861588e4acd8joshualitt coverageType = Coverage::kSolid_Type; 111df0c55785033c191d2d509c22662861588e4acd8joshualitt } else { 112df0c55785033c191d2d509c22662861588e4acd8joshualitt coverageType = Coverage::kAttribute_Type; 1131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1148c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon LocalCoords::Type localCoordsType = 1158c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon usesLocalCoords ? LocalCoords::kUsePosition_Type : LocalCoords::kUnused_Type; 1163de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon return MakeForDeviceSpace(Color::kPremulGrColorAttribute_Type, coverageType, localCoordsType, 1173de0aee181b8fe0013b15100cba7381eb0468db4Brian Salomon viewMatrix); 1181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 1191a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 120780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomonclass AAFlatteningConvexPathOp final : public GrMeshDrawOp { 1211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholaspublic: 12225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 123649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon static std::unique_ptr<GrMeshDrawOp> Make(GrColor color, 124649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkMatrix& viewMatrix, 125649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon const SkPath& path, 126649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkScalar strokeWidth, 127649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkStrokeRec::Style style, 128649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkPaint::Join join, 129649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon SkScalar miterLimit) { 130649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon return std::unique_ptr<GrMeshDrawOp>(new AAFlatteningConvexPathOp( 131f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon color, viewMatrix, path, strokeWidth, style, join, miterLimit)); 1321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1331a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 134780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const char* name() const override { return "AAFlatteningConvexPathOp"; } 1357c3e7180948766321c51d165737555e78910de51Brian Salomon 1367c3e7180948766321c51d165737555e78910de51Brian Salomon SkString dumpInfo() const override { 1377c3e7180948766321c51d165737555e78910de51Brian Salomon SkString string; 138780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon for (const auto& path : fPaths) { 139780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon string.appendf( 140780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon "Color: 0x%08x, StrokeWidth: %.2f, Style: %d, Join: %d, " 141780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon "MiterLimit: %.2f\n", 142780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon path.fColor, path.fStrokeWidth, path.fStyle, path.fJoin, path.fMiterLimit); 1437c3e7180948766321c51d165737555e78910de51Brian Salomon } 1447c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(DumpPipelineInfo(*this->pipeline())); 1457c3e7180948766321c51d165737555e78910de51Brian Salomon string.append(INHERITED::dumpInfo()); 1467c3e7180948766321c51d165737555e78910de51Brian Salomon return string; 1477c3e7180948766321c51d165737555e78910de51Brian Salomon } 1481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 149e46f9feb44780a6269c6dcfe993f4215427fd98ebsalomonprivate: 150780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon AAFlatteningConvexPathOp(GrColor color, 151780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix, 152780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkPath& path, 153780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar strokeWidth, 154780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkStrokeRec::Style style, 155780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkPaint::Join join, 156780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar miterLimit) 157780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon : INHERITED(ClassID()) { 158780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.emplace_back( 159780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon PathData{color, viewMatrix, path, strokeWidth, style, join, miterLimit}); 160780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon 161780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // compute bounds 162780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkRect bounds = path.getBounds(); 163780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkScalar w = strokeWidth; 164780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon if (w > 0) { 165780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon w /= 2; 166780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // If the half stroke width is < 1 then we effectively fallback to bevel joins. 167780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon if (SkPaint::kMiter_Join == join && w > 1.f) { 168780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon w *= miterLimit; 169780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 170780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bounds.outset(w, w); 171780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 172780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kYes, IsZeroArea::kNo); 173780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon } 174780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon 175c0b642ca48d58416409e555549434066f09692b7Brian Salomon void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 176c0b642ca48d58416409e555549434066f09692b7Brian Salomon GrPipelineAnalysisCoverage* coverage) const override { 177c0b642ca48d58416409e555549434066f09692b7Brian Salomon color->setToConstant(fPaths[0].fColor); 178c0b642ca48d58416409e555549434066f09692b7Brian Salomon *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 17992aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon } 18092aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon 18192aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override { 18292aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon optimizations.getOverrideColorIfSet(&fPaths[0].fColor); 18392aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fUsesLocalCoords = optimizations.readsLocalCoords(); 18492aee3d6857386f2b5b8e1148e680a7b58e9b1fcBrian Salomon fCanTweakAlphaForCoverage = optimizations.canTweakAlphaForCoverage(); 1851a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 1861a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 187dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon void draw(GrMeshDrawOp::Target* target, const GrGeometryProcessor* gp, int vertexCount, 188144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt size_t vertexStride, void* vertices, int indexCount, uint16_t* indices) const { 1891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount == 0 || indexCount == 0) { 1901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 1911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 192397536cabe12a9936659870dd220c869789424bacdalton const GrBuffer* vertexBuffer; 1930e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel GrMesh mesh; 1941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int firstVertex; 195002c2ce66be69d41632c9603ce62c50f04156518mtklein void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, 1967539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon &firstVertex); 1971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!verts) { 1981a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate vertices\n"); 1991a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(verts, vertices, vertexCount * vertexStride); 2021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 203397536cabe12a9936659870dd220c869789424bacdalton const GrBuffer* indexBuffer; 2041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int firstIndex; 2057539856c1b9cbb1886a6a498cc534b77fc83ddb2bsalomon uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); 2061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!idxs) { 2071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkDebugf("Could not allocate indices\n"); 2081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2101a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas memcpy(idxs, indices, indexCount * sizeof(uint16_t)); 2110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer, firstVertex, 2120e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel firstIndex, vertexCount, indexCount); 213342bfc25de5b0452b1551bf9db4bf45eac7718b2bsalomon target->draw(gp, mesh); 2141a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 215002c2ce66be69d41632c9603ce62c50f04156518mtklein 216144c3c8b7ff3ebc389b41211f3388fb24a7ff0c2joshualitt void onPrepareDraws(Target* target) const override { 2171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); 2181a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 219df0c55785033c191d2d509c22662861588e4acd8joshualitt // Setup GrGeometryProcessor 2208c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon sk_sp<GrGeometryProcessor> gp(create_fill_gp( 2218c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon canTweakAlphaForCoverage, this->viewMatrix(), this->usesLocalCoords())); 222df0c55785033c191d2d509c22662861588e4acd8joshualitt if (!gp) { 223df0c55785033c191d2d509c22662861588e4acd8joshualitt SkDebugf("Couldn't create a GrGeometryProcessor\n"); 2241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return; 2251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas size_t vertexStride = gp->getVertexStride(); 2281a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2291a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkASSERT(canTweakAlphaForCoverage ? 2301a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) : 2311a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); 2321a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 233780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon int instanceCount = fPaths.count(); 2341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int vertexCount = 0; 2361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int indexCount = 0; 2371a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxVertices = DEFAULT_BUFFER_SIZE; 2381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int maxIndices = DEFAULT_BUFFER_SIZE; 239002c2ce66be69d41632c9603ce62c50f04156518mtklein uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride); 240002c2ce66be69d41632c9603ce62c50f04156518mtklein uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t)); 2411a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas for (int i = 0; i < instanceCount; i++) { 242780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const PathData& args = fPaths[i]; 2438c170971f182d47bc9af71fc88a607740d03dfd5robertphillips GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth, 2448c170971f182d47bc9af71fc88a607740d03dfd5robertphillips args.fJoin, args.fMiterLimit); 2451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2461a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (!tess.tessellate(args.fViewMatrix, args.fPath)) { 2471a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas continue; 2481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 2501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentIndices = tess.numIndices(); 2511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkASSERT(currentIndices <= UINT16_MAX); 2521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > UINT16_MAX) { 253002c2ce66be69d41632c9603ce62c50f04156518mtklein // if we added the current instance, we would overflow the indices we can store in a 2541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas // uint16_t. Draw what we've got so far and reset. 25506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman this->draw(target, gp.get(), 25606ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman vertexCount, vertexStride, vertices, indexCount, indices); 2571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount = 0; 2581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount = 0; 2591a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2601a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas int currentVertices = tess.numPts(); 2611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (vertexCount + currentVertices > maxVertices) { 2621a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2); 263002c2ce66be69d41632c9603ce62c50f04156518mtklein vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride); 2641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (indexCount + currentIndices > maxIndices) { 2661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2); 267002c2ce66be69d41632c9603ce62c50f04156518mtklein indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t)); 2681a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2691a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 270002c2ce66be69d41632c9603ce62c50f04156518mtklein extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor, 2711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount, indices + indexCount, canTweakAlphaForCoverage); 2721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas vertexCount += currentVertices; 2731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas indexCount += currentIndices; 2741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 27506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman this->draw(target, gp.get(), vertexCount, vertexStride, vertices, indexCount, indices); 276002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(vertices); 277002c2ce66be69d41632c9603ce62c50f04156518mtklein sk_free(indices); 2781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 28025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { 281780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>(); 282abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 283abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon that->bounds(), caps)) { 2848cab9a7685e872427e6f0388f149575a9b6016eejoshualitt return false; 2858cab9a7685e872427e6f0388f149575a9b6016eejoshualitt } 2868cab9a7685e872427e6f0388f149575a9b6016eejoshualitt 2871a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); 2881a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 2891a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return false; 2901a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2911a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 292780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // In the event of two ops, one who can tweak, one who cannot, we just fall back to not 293780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon // tweaking 2941a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage()) { 295780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fCanTweakAlphaForCoverage = false; 2961a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 2971a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 298780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon fPaths.push_back_n(that->fPaths.count(), that->fPaths.begin()); 29988cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->joinBounds(*that); 3001a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas } 3021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 303780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bool usesLocalCoords() const { return fUsesLocalCoords; } 304780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bool canTweakAlphaForCoverage() const { return fCanTweakAlphaForCoverage; } 305780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon const SkMatrix& viewMatrix() const { return fPaths[0].fViewMatrix; } 3061a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 307780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon struct PathData { 3080432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon GrColor fColor; 3090432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkMatrix fViewMatrix; 3100432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath fPath; 3110432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fStrokeWidth; 3128c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkStrokeRec::Style fStyle; 3130432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join fJoin; 3140432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar fMiterLimit; 3150432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon }; 3160432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon 317780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bool fUsesLocalCoords; 318780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon bool fCanTweakAlphaForCoverage; 319780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon SkSTArray<1, PathData, true> fPaths; 3201b55a963a2374a14bb82eb887bb99ee91680f0ebreed 321dad2923b8ec9270d810c1e8e76da8e6768d8f9ddBrian Salomon typedef GrMeshDrawOp INHERITED; 3221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}; 3231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3240aff2fa82a5fa9f99aa77327dac3e9e803b4ed07bsalomonbool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { 3251105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(), 326de83b41cc7fc5bd1398e06c011e698215261665fjoshualitt "GrAALinearizingConvexPathRenderer::onDrawPath"); 3271105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman SkASSERT(!args.fRenderTargetContext->isUnifiedMultisampled()); 3288acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon SkASSERT(!args.fShape->isEmpty()); 3298c170971f182d47bc9af71fc88a607740d03dfd5robertphillips SkASSERT(!args.fShape->style().pathEffect()); 330ecbc12b1c1c72de0cf7bba4a3f6a7cce4f43bf41csmartdalton 3310432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPath path; 3320432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon args.fShape->asPath(&path); 3338acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon bool fill = args.fShape->style().isSimpleFill(); 3348acedde5970ce70de6d9791ffeda87a65af4ed07bsalomon const SkStrokeRec& stroke = args.fShape->style().strokeRec(); 3350432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar strokeWidth = fill ? -1.0f : stroke.getWidth(); 3360432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkPaint::Join join = fill ? SkPaint::Join::kMiter_Join : stroke.getJoin(); 3370432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon SkScalar miterLimit = stroke.getMiter(); 3381a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 339649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon std::unique_ptr<GrMeshDrawOp> op = 34082f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon AAFlatteningConvexPathOp::Make(args.fPaint.getColor(), *args.fViewMatrix, path, 341780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon strokeWidth, stroke.getStyle(), join, miterLimit); 342976f5f0dc5e907d1ca50685fad117bd15d7fc87brobertphillips 34382f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon GrPipelineBuilder pipelineBuilder(std::move(args.fPaint), args.fAAType); 344bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon pipelineBuilder.setUserStencil(args.fUserStencilSettings); 345bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon 346649a3411f99a8aea3c46e4ef1f495f61b9801164Brian Salomon args.fRenderTargetContext->addMeshDrawOp(pipelineBuilder, *args.fClip, std::move(op)); 347bb24383abb724c516e472af4eec68f2c3f17a6d0bsalomon 3481a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas return true; 3491a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3501a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas/////////////////////////////////////////////////////////////////////////////////////////////////// 3521a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3536f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 3541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3555ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian SalomonDRAW_OP_TEST_DEFINE(AAFlatteningConvexPathOp) { 3560432dd6ee62d0c1c1ca67b7f6f6fcf3de75aaf77bsalomon GrColor color = GrRandomColor(random); 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 } 3798c170971f182d47bc9af71fc88a607740d03dfd5robertphillips 380780dad1ab9469828e3ef317ad9aea12f9c0a270aBrian Salomon return AAFlatteningConvexPathOp::Make(color, viewMatrix, path, strokeWidth, style, join, 3815ec9def2dd7bba572398ff2aa9361fbbb3b478edBrian Salomon miterLimit); 3821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas} 3831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas 3841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#endif 385