| Index: src/gpu/batches/GrRegionBatch.cpp
|
| diff --git a/src/gpu/batches/GrRegionBatch.cpp b/src/gpu/batches/GrRegionBatch.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..271f6c5b7ee1e0290a63bf7c9b81669b5aa52c51
|
| --- /dev/null
|
| +++ b/src/gpu/batches/GrRegionBatch.cpp
|
| @@ -0,0 +1,176 @@
|
| +/*
|
| + * Copyright 2016 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "GrRegionBatch.h"
|
| +
|
| +#include "GrDefaultGeoProcFactory.h"
|
| +#include "GrBatchFlushState.h"
|
| +#include "GrResourceProvider.h"
|
| +#include "GrVertexBatch.h"
|
| +#include "SkMatrixPriv.h"
|
| +#include "SkRegion.h"
|
| +
|
| +static const int kVertsPerInstance = 4;
|
| +static const int kIndicesPerInstance = 6;
|
| +
|
| +static sk_sp<GrGeometryProcessor> make_gp(bool readsCoverage) {
|
| + using namespace GrDefaultGeoProcFactory;
|
| + Color color(Color::kAttribute_Type);
|
| + Coverage coverage(readsCoverage ? Coverage::kSolid_Type : Coverage::kNone_Type);
|
| +
|
| + LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
|
| + return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
|
| +}
|
| +
|
| +static int tesselate_region(intptr_t vertices,
|
| + size_t vertexStride,
|
| + GrColor color,
|
| + const SkMatrix& viewMatrix,
|
| + const SkRegion& region) {
|
| + SkRegion::Iterator iter(region);
|
| +
|
| + intptr_t verts = vertices;
|
| + while (!iter.done()) {
|
| + SkIRect rect = iter.rect();
|
| + SkPoint* position = (SkPoint*) verts;
|
| + position->setIRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
|
| +
|
| + static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
|
| + SkPoint* localPosition = (SkPoint*) (verts + kLocalOffset);
|
| + localPosition->setIRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
|
| +
|
| + static const int kColorOffset = sizeof(SkPoint);
|
| + GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset);
|
| + for (int i = 0; i < kVertsPerInstance; i++) {
|
| + *vertColor = color;
|
| + vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride);
|
| + }
|
| +
|
| + verts += vertexStride * kVertsPerInstance;
|
| + iter.next();
|
| + }
|
| +
|
| + SkPoint* positions = reinterpret_cast<SkPoint*>(vertices);
|
| + int numRects = region.computeRegionComplexity();
|
| + SkMatrixPriv::MapPointsWithStride(viewMatrix, positions, vertexStride,
|
| + numRects * kVertsPerInstance);
|
| +
|
| + return numRects;
|
| +}
|
| +
|
| +class RegionBatch : public GrVertexBatch {
|
| +public:
|
| + DEFINE_BATCH_CLASS_ID
|
| +
|
| + RegionBatch(GrColor color, const SkMatrix& viewMatrix, const SkRegion& region)
|
| + : INHERITED(ClassID()) {
|
| +
|
| + RegionInfo& info = fRegions.push_back();
|
| + info.fColor = color;
|
| + info.fViewMatrix = viewMatrix;
|
| + info.fRegion = region;
|
| +
|
| + SkRect bounds = SkRect::Make(region.getBounds());
|
| + this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
|
| + }
|
| +
|
| + const char* name() const override { return "GrRegionBatch"; }
|
| +
|
| + SkString dumpInfo() const override {
|
| + SkString str;
|
| + str.appendf("# batched: %d\n", fRegions.count());
|
| + for (int i = 0; i < fRegions.count(); ++i) {
|
| + const RegionInfo& info = fRegions[i];
|
| + str.appendf("%d: Color: 0x%08x, Region with %d rects\n",
|
| + i, info.fColor, info.fRegion.computeRegionComplexity());
|
| + }
|
| + str.append(INHERITED::dumpInfo());
|
| + return str;
|
| + }
|
| +
|
| + void computePipelineOptimizations(GrInitInvariantOutput* color,
|
| + GrInitInvariantOutput* coverage,
|
| + GrBatchToXPOverrides* overrides) const override {
|
| + // When this is called on a batch, there is only one region.
|
| + color->setKnownFourComponents(fRegions[0].fColor);
|
| + coverage->setKnownSingleComponent(0xff);
|
| + }
|
| +
|
| + void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
|
| + overrides.getOverrideColorIfSet(&fRegions[0].fColor);
|
| + fOverrides = overrides;
|
| + }
|
| +
|
| +private:
|
| +
|
| + void onPrepareDraws(Target* target) const override {
|
| + sk_sp<GrGeometryProcessor> gp = make_gp(fOverrides.readsCoverage());
|
| + if (!gp) {
|
| + SkDebugf("Couldn't create GrGeometryProcessor\n");
|
| + return;
|
| + }
|
| + SkASSERT(gp->getVertexStride() ==
|
| + sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
|
| +
|
| + int numRegions = fRegions.count();
|
| + int numRects = 0;
|
| + for (int i = 0; i < numRegions; i++) {
|
| + numRects += fRegions[i].fRegion.computeRegionComplexity();
|
| + }
|
| +
|
| + size_t vertexStride = gp->getVertexStride();
|
| + SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
|
| + InstancedHelper helper;
|
| + void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
|
| + indexBuffer, kVertsPerInstance, kIndicesPerInstance, numRects);
|
| + if (!vertices || !indexBuffer) {
|
| + SkDebugf("Could not allocate vertices\n");
|
| + return;
|
| + }
|
| +
|
| + intptr_t verts = reinterpret_cast<intptr_t>(vertices);
|
| + for (int i = 0; i < numRegions; i++) {
|
| + int numRectsInRegion = tesselate_region(verts, vertexStride, fRegions[i].fColor,
|
| + fRegions[i].fViewMatrix, fRegions[i].fRegion);
|
| + verts += numRectsInRegion * kVertsPerInstance * vertexStride;
|
| + }
|
| + helper.recordDraw(target, gp.get());
|
| + }
|
| +
|
| + bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
|
| + RegionBatch* that = t->cast<RegionBatch>();
|
| + if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
|
| + that->bounds(), caps)) {
|
| + return false;
|
| + }
|
| +
|
| + fRegions.push_back_n(that->fRegions.count(), that->fRegions.begin());
|
| + this->joinBounds(*that);
|
| + return true;
|
| + }
|
| +
|
| + struct RegionInfo {
|
| + GrColor fColor;
|
| + SkMatrix fViewMatrix;
|
| + SkRegion fRegion;
|
| + };
|
| +
|
| + GrXPOverridesForBatch fOverrides;
|
| + SkSTArray<1, RegionInfo, true> fRegions;
|
| +
|
| + typedef GrVertexBatch INHERITED;
|
| +};
|
| +
|
| +namespace GrRegionBatch {
|
| +
|
| +GrDrawBatch* Create(GrColor color,
|
| + const SkMatrix& viewMatrix,
|
| + const SkRegion& region) {
|
| + return new RegionBatch(color, viewMatrix, region);
|
| +}
|
| +
|
| +};
|
|
|