GrRegionOp.cpp revision cc319b95a58ae15e88c3c028b8726e7cab9121ff
1cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett/* 2cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * Copyright 2016 Google Inc. 3cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * 4cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * Use of this source code is governed by a BSD-style license that can be 5cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett * found in the LICENSE file. 6cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett */ 7cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 8cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrRegionBatch.h" 9cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 10cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrDefaultGeoProcFactory.h" 11cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrBatchFlushState.h" 12cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrResourceProvider.h" 13cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "GrVertexBatch.h" 14cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkMatrixPriv.h" 15cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett#include "SkRegion.h" 16cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 17cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kVertsPerInstance = 4; 18cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic const int kIndicesPerInstance = 6; 19cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 20cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic sk_sp<GrGeometryProcessor> make_gp(bool readsCoverage) { 21cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett using namespace GrDefaultGeoProcFactory; 22cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett Color color(Color::kAttribute_Type); 23cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type); 24cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 25cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett LocalCoords localCoords(LocalCoords::kHasExplicit_Type); 26cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I()); 27cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett} 28cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 29cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettstatic int tesselate_region(intptr_t vertices, 30cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett size_t vertexStride, 31cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrColor color, 32cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const SkMatrix& viewMatrix, 33cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const SkRegion& region) { 34cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkRegion::Iterator iter(region); 35cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 36cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett intptr_t verts = vertices; 37cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett while (!iter.done()) { 38cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkIRect rect = iter.rect(); 39cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkPoint* position = (SkPoint*) verts; 40cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett position->setIRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); 41cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 42cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); 43cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkPoint* localPosition = (SkPoint*) (verts + kLocalOffset); 44cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett localPosition->setIRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride); 45cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 46cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett static const int kColorOffset = sizeof(SkPoint); 47cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset); 48cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < kVertsPerInstance; i++) { 49cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett *vertColor = color; 50cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride); 51cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 52cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 53cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett verts += vertexStride * kVertsPerInstance; 54cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett iter.next(); 55cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 56cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 57cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkPoint* positions = reinterpret_cast<SkPoint*>(vertices); 58cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett int numRects = region.computeRegionComplexity(); 59cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkMatrixPriv::MapPointsWithStride(viewMatrix, positions, vertexStride, 60cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett numRects * kVertsPerInstance); 61cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 62cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return numRects; 63cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett} 64cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 65cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettclass RegionBatch : public GrVertexBatch { 66cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettpublic: 67cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett DEFINE_BATCH_CLASS_ID 68cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 69cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett RegionBatch(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region) 70cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett : INHERITED(ClassID()) { 71cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 72cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett RegionInfo& info = fRegions.push_back(); 73cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett info.fColor = color; 74cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett info.fViewMatrix = viewMatrix; 75cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett info.fRegion = region; 76cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 77cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkRect bounds = SkRect::Make(region.getBounds()); 78cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); 79cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 80cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 81cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const char* name() const override { return "GrRegionBatch"; } 82cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 83cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkString dumpInfo() const override { 84cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkString str; 85cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett str.appendf("# batched: %d\n", fRegions.count()); 86cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < fRegions.count(); ++i) { 87cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const RegionInfo& info = fRegions[i]; 88cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett str.appendf("%d: Color: 0x%08x, Region with %d rects\n", 89cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett i, info.fColor, info.fRegion.computeRegionComplexity()); 90cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 91cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett str.append(INHERITED::dumpInfo()); 92cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return str; 93cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 94cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 95cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett void computePipelineOptimizations(GrInitInvariantOutput* color, 96cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrInitInvariantOutput* coverage, 97cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrBatchToXPOverrides* overrides) const override { 98cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett // When this is called on a batch, there is only one region. 99cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett color->setKnownFourComponents(fRegions[0].fColor); 100cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett coverage->setKnownSingleComponent(0xff); 101cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 102cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 103cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 104cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett overrides.getOverrideColorIfSet(&fRegions[0].fColor); 105cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett fOverrides = overrides; 106cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 107cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 108cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettprivate: 109cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 110cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett void onPrepareDraws(Target* target) const override { 111cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett sk_sp<GrGeometryProcessor> gp = make_gp(fOverrides.readsCoverage()); 112cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett if (!gp) { 113cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkDebugf("Couldn't create GrGeometryProcessor\n"); 114cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return; 115cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 116cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkASSERT(gp->getVertexStride() == 117cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr)); 118cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 119cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett int numRegions = fRegions.count(); 120cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett int numRects = 0; 121cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < numRegions; i++) { 122cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett numRects += fRegions[i].fRegion.computeRegionComplexity(); 123cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 124cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 125cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett size_t vertexStride = gp->getVertexStride(); 126cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer()); 127cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett InstancedHelper helper; 128cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, 129cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett indexBuffer, kVertsPerInstance, kIndicesPerInstance, numRects); 130cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett if (!vertices || !indexBuffer) { 131cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkDebugf("Could not allocate vertices\n"); 132cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return; 133cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 134cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 135cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett intptr_t verts = reinterpret_cast<intptr_t>(vertices); 136cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett for (int i = 0; i < numRegions; i++) { 137cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett int numRectsInRegion = tesselate_region(verts, vertexStride, fRegions[i].fColor, 138cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett fRegions[i].fViewMatrix, fRegions[i].fRegion); 139cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett verts += numRectsInRegion * kVertsPerInstance * vertexStride; 140cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 141cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett helper.recordDraw(target, gp.get()); 142cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 143cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 144cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 145cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett RegionBatch* that = t->cast<RegionBatch>(); 146cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 147cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett that->bounds(), caps)) { 148cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return false; 149cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 150cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 151cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin()); 152cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett this->joinBounds(*that); 153cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return true; 154cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett } 155cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 156cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett struct RegionInfo { 157cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrColor fColor; 158cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkMatrix fViewMatrix; 159cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkRegion fRegion; 160cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett }; 161cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 162cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett GrXPOverridesForBatch fOverrides; 163cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett SkSTArray<1, RegionInfo, true> fRegions; 164cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 165cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett typedef GrVertexBatch INHERITED; 166cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}; 167cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 168cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettnamespace GrRegionBatch { 169cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 170cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarettGrDrawBatch* Create(GrColor color, 171cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const SkMatrix& viewMatrix, 172cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett const SkRegion& region) { 173cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett return new RegionBatch(color, viewMatrix, region); 174cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett} 175cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett 176cc319b95a58ae15e88c3c028b8726e7cab9121ffmsarett}; 177