aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2018-06-13 15:28:19 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-13 21:53:36 +0000
commit42c2115fc32e43c252284082a6e2473cef76e401 (patch)
treeadddeb33229a57e95992c8cad6da609b3c9862a8 /src/gpu/ccpr
parent527a297d6e2410277ff41c40dcbb56410d6a9118 (diff)
ccpr: Initialize the atlas size more intelligently
Rather than always starting the atlas at 1024 x 1024, begin with the first pow2 dimensions whose area is theoretically large enough to contain the pending paths. Bug: skia: Change-Id: I263e77ff6a697e865f6b3b62b9df7002225f9544 Reviewed-on: https://skia-review.googlesource.com/133660 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/gpu/ccpr')
-rw-r--r--src/gpu/ccpr/GrCCAtlas.cpp46
-rw-r--r--src/gpu/ccpr/GrCCAtlas.h25
-rw-r--r--src/gpu/ccpr/GrCCClipPath.cpp15
-rw-r--r--src/gpu/ccpr/GrCCDrawPathsOp.cpp47
-rw-r--r--src/gpu/ccpr/GrCCDrawPathsOp.h24
-rw-r--r--src/gpu/ccpr/GrCCPerFlushResources.cpp32
-rw-r--r--src/gpu/ccpr/GrCCPerFlushResources.h34
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp54
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.h2
9 files changed, 166 insertions, 113 deletions
diff --git a/src/gpu/ccpr/GrCCAtlas.cpp b/src/gpu/ccpr/GrCCAtlas.cpp
index df84ed75a4..551b2a048e 100644
--- a/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/src/gpu/ccpr/GrCCAtlas.cpp
@@ -21,9 +21,6 @@
#include "ccpr/GrCCPathParser.h"
#include "ops/GrDrawOp.h"
-static constexpr int kAtlasMinSize = 1024;
-static constexpr int kPadding = 1;
-
class GrCCAtlas::Node {
public:
Node(std::unique_ptr<Node> previous, int l, int t, int r, int b)
@@ -97,15 +94,27 @@ private:
typedef GrDrawOp INHERITED;
};
-GrCCAtlas::GrCCAtlas(const GrCaps& caps, int minSize)
- : fMaxAtlasSize(SkTMax(minSize, caps.maxPreferredRenderTargetSize())) {
- // Caller should have cropped any paths to the destination render target instead of asking for
- // an atlas larger than maxRenderTargetSize.
- SkASSERT(fMaxAtlasSize <= caps.maxRenderTargetSize());
- int initialSize = GrNextPow2(minSize + kPadding);
- initialSize = SkTMax(kAtlasMinSize, initialSize);
- initialSize = SkTMin(initialSize, fMaxAtlasSize);
- fHeight = fWidth = initialSize;
+GrCCAtlas::GrCCAtlas(const Specs& specs)
+ : fMaxTextureSize(SkTMax(SkTMax(specs.fMinHeight, specs.fMinWidth),
+ specs.fMaxPreferredTextureSize)) {
+ SkASSERT(specs.fMaxPreferredTextureSize > 0);
+
+ // Begin with the first pow2 dimensions whose area is theoretically large enough to contain the
+ // pending paths, favoring height over width if necessary.
+ int log2area = SkNextLog2(SkTMax(specs.fApproxNumPixels, 1));
+ fHeight = 1 << ((log2area + 1) / 2);
+ fWidth = 1 << (log2area / 2);
+
+ fWidth = SkTClamp(fWidth, specs.fMinTextureSize, specs.fMaxPreferredTextureSize);
+ fHeight = SkTClamp(fHeight, specs.fMinTextureSize, specs.fMaxPreferredTextureSize);
+
+ if (fWidth < specs.fMinWidth || fHeight < specs.fMinHeight) {
+ // They want to stuff a particularly large path into the atlas. Just punt and go with their
+ // min width and height. The atlas will grow as needed.
+ fWidth = SkTMin(specs.fMinWidth + kPadding, fMaxTextureSize);
+ fHeight = SkTMin(specs.fMinHeight + kPadding, fMaxTextureSize);
+ }
+
fTopNode = skstd::make_unique<Node>(nullptr, 0, 0, fWidth, fHeight);
}
@@ -128,26 +137,26 @@ bool GrCCAtlas::addRect(int w, int h, SkIPoint16* loc) {
bool GrCCAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
for (Node* node = fTopNode.get(); node; node = node->previous()) {
- if (node->addRect(w, h, loc, fMaxAtlasSize)) {
+ if (node->addRect(w, h, loc, fMaxTextureSize)) {
return true;
}
}
// The rect didn't fit. Grow the atlas and try again.
do {
- if (fWidth == fMaxAtlasSize && fHeight == fMaxAtlasSize) {
+ if (fWidth == fMaxTextureSize && fHeight == fMaxTextureSize) {
return false;
}
if (fHeight <= fWidth) {
int top = fHeight;
- fHeight = SkTMin(fHeight * 2, fMaxAtlasSize);
+ fHeight = SkTMin(fHeight * 2, fMaxTextureSize);
fTopNode = skstd::make_unique<Node>(std::move(fTopNode), 0, top, fWidth, fHeight);
} else {
int left = fWidth;
- fWidth = SkTMin(fWidth * 2, fMaxAtlasSize);
+ fWidth = SkTMin(fWidth * 2, fMaxTextureSize);
fTopNode = skstd::make_unique<Node>(std::move(fTopNode), left, 0, fWidth, fHeight);
}
- } while (!fTopNode->addRect(w, h, loc, fMaxAtlasSize));
+ } while (!fTopNode->addRect(w, h, loc, fMaxTextureSize));
return true;
}
@@ -156,6 +165,9 @@ sk_sp<GrRenderTargetContext> GrCCAtlas::finalize(GrOnFlushResourceProvider* onFl
sk_sp<const GrCCPathParser> parser) {
SkASSERT(fCoverageCountBatchID);
SkASSERT(!fTextureProxy);
+ // Caller should have cropped any paths to the destination render target instead of asking for
+ // an atlas larger than maxRenderTargetSize.
+ SkASSERT(fMaxTextureSize <= onFlushRP->caps()->maxRenderTargetSize());
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
diff --git a/src/gpu/ccpr/GrCCAtlas.h b/src/gpu/ccpr/GrCCAtlas.h
index 184022ee96..b30bdbec6f 100644
--- a/src/gpu/ccpr/GrCCAtlas.h
+++ b/src/gpu/ccpr/GrCCAtlas.h
@@ -27,8 +27,22 @@ struct SkIPoint16;
class GrCCAtlas {
public:
using CoverageCountBatchID = int;
+ static constexpr int kPadding = 1; // Amount of padding below and to the right of each path.
- GrCCAtlas(const GrCaps&, int minSize);
+ // This struct encapsulates the minimum and desired requirements for an atlas, as well as an
+ // approximate number of pixels to help select a good initial size.
+ struct Specs {
+ int fMaxPreferredTextureSize = 0;
+ int fMinTextureSize = 0;
+ int fMinWidth = 0; // If there are 100 20x10 paths, this should be 20.
+ int fMinHeight = 0; // If there are 100 20x10 paths, this should be 10.
+ int fApproxNumPixels = 0;
+
+ // Add space for a rect in the desired atlas specs.
+ void accountForSpace(int width, int height);
+ };
+
+ GrCCAtlas(const Specs&);
~GrCCAtlas();
bool addRect(int devWidth, int devHeight, SkIPoint16* loc);
@@ -51,8 +65,7 @@ private:
bool internalPlaceRect(int w, int h, SkIPoint16* loc);
- const int fMaxAtlasSize;
-
+ const int fMaxTextureSize;
int fWidth, fHeight;
std::unique_ptr<Node> fTopNode;
SkISize fDrawBounds = {0, 0};
@@ -61,4 +74,10 @@ private:
sk_sp<GrTextureProxy> fTextureProxy;
};
+inline void GrCCAtlas::Specs::accountForSpace(int width, int height) {
+ fMinWidth = SkTMax(width, fMinWidth);
+ fMinHeight = SkTMax(height, fMinHeight);
+ fApproxNumPixels += (width + kPadding) * (height + kPadding);
+}
+
#endif
diff --git a/src/gpu/ccpr/GrCCClipPath.cpp b/src/gpu/ccpr/GrCCClipPath.cpp
index 9b8a73752c..c98865765e 100644
--- a/src/gpu/ccpr/GrCCClipPath.cpp
+++ b/src/gpu/ccpr/GrCCClipPath.cpp
@@ -48,12 +48,23 @@ void GrCCClipPath::init(GrProxyProvider* proxyProvider,
fAccessRect = accessRect;
}
+void GrCCClipPath::accountForOwnPath(GrCCPerFlushResourceSpecs* resourceSpecs) const {
+ SkASSERT(this->isInitialized());
+
+ ++resourceSpecs->fNumClipPaths;
+ resourceSpecs->fParsingPathStats.statPath(fDeviceSpacePath);
+
+ SkIRect ibounds;
+ if (ibounds.intersect(fAccessRect, fPathDevIBounds)) {
+ resourceSpecs->fAtlasSpecs.accountForSpace(ibounds.width(), ibounds.height());
+ }
+}
+
void GrCCClipPath::renderPathInAtlas(GrCCPerFlushResources* resources,
GrOnFlushResourceProvider* onFlushRP) {
SkASSERT(this->isInitialized());
SkASSERT(!fHasAtlas);
- fAtlas = resources->renderDeviceSpacePathInAtlas(*onFlushRP->caps(), fAccessRect,
- fDeviceSpacePath, fPathDevIBounds,
+ fAtlas = resources->renderDeviceSpacePathInAtlas(fAccessRect, fDeviceSpacePath, fPathDevIBounds,
&fAtlasOffsetX, &fAtlasOffsetY);
SkDEBUGCODE(fHasAtlas = true);
}
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.cpp b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
index 01913fa252..f29fca2f04 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.cpp
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.cpp
@@ -13,15 +13,6 @@
#include "ccpr/GrCCPerFlushResources.h"
#include "ccpr/GrCoverageCountingPathRenderer.h"
-GrCCDrawPathsOp* GrCCDrawPathsOp::Make(GrContext* context,
- GrPaint&& paint,
- const SkIRect& clipIBounds,
- const SkMatrix& m,
- const SkPath& path,
- const SkRect& devBounds) {
- return new GrCCDrawPathsOp(std::move(paint), clipIBounds, m, path, devBounds);
-}
-
static bool has_coord_transforms(const GrPaint& paint) {
GrFragmentProcessor::Iter iter(paint);
while (const GrFragmentProcessor* fp = iter.next()) {
@@ -32,13 +23,25 @@ static bool has_coord_transforms(const GrPaint& paint) {
return false;
}
-GrCCDrawPathsOp::GrCCDrawPathsOp(GrPaint&& paint, const SkIRect& clipIBounds, const SkMatrix& m,
- const SkPath& path, const SkRect& devBounds)
+std::unique_ptr<GrCCDrawPathsOp> GrCCDrawPathsOp::Make(GrContext*, const SkIRect& clipIBounds,
+ const SkMatrix& m, const SkPath& path,
+ const SkRect& devBounds, GrPaint&& paint) {
+ SkIRect looseClippedIBounds;
+ devBounds.roundOut(&looseClippedIBounds); // GrCCPathParser might find slightly tighter bounds.
+ if (!looseClippedIBounds.intersect(clipIBounds)) {
+ return nullptr;
+ }
+ return std::unique_ptr<GrCCDrawPathsOp>(
+ new GrCCDrawPathsOp(looseClippedIBounds, m, path, devBounds, std::move(paint)));
+}
+
+GrCCDrawPathsOp::GrCCDrawPathsOp(const SkIRect& looseClippedIBounds, const SkMatrix& m,
+ const SkPath& path, const SkRect& devBounds, GrPaint&& paint)
: GrDrawOp(ClassID())
- , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
, fViewMatrixIfUsingLocalCoords(has_coord_transforms(paint) ? m : SkMatrix::I())
- , fDraws({clipIBounds, m, path, paint.getColor(), nullptr})
- , fProcessors(std::move(paint)) {
+ , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint))
+ , fDraws({looseClippedIBounds, m, path, paint.getColor(), nullptr})
+ , fProcessors(std::move(paint)) { // Paint must be moved after fetching its color above.
SkDEBUGCODE(fBaseInstance = -1);
// FIXME: intersect with clip bounds to (hopefully) improve batching.
// (This is nontrivial due to assumptions in generating the octagon cover geometry.)
@@ -90,13 +93,13 @@ void GrCCDrawPathsOp::wasRecorded(GrCCPerOpListPaths* owningPerOpListPaths) {
fOwningPerOpListPaths = owningPerOpListPaths;
}
-int GrCCDrawPathsOp::countPaths(GrCCPathParser::PathStats* stats) const {
- int numPaths = 0;
+void GrCCDrawPathsOp::accountForOwnPaths(GrCCPerFlushResourceSpecs* resourceSpecs) const {
for (const GrCCDrawPathsOp::SingleDraw& draw : fDraws) {
- stats->statPath(draw.fPath);
- ++numPaths;
+ ++resourceSpecs->fNumRenderedPaths;
+ resourceSpecs->fParsingPathStats.statPath(draw.fPath);
+ resourceSpecs->fAtlasSpecs.accountForSpace(draw.fLooseClippedIBounds.width(),
+ draw.fLooseClippedIBounds.height());
}
- return numPaths;
}
void GrCCDrawPathsOp::setupResources(GrCCPerFlushResources* resources,
@@ -112,9 +115,9 @@ void GrCCDrawPathsOp::setupResources(GrCCPerFlushResources* resources,
// bounding boxes to generate an octagon that circumscribes the path.
SkRect devBounds, devBounds45;
int16_t atlasOffsetX, atlasOffsetY;
- GrCCAtlas* atlas = resources->renderPathInAtlas(*onFlushRP->caps(), draw.fClipIBounds,
- draw.fMatrix, draw.fPath, &devBounds,
- &devBounds45, &atlasOffsetX, &atlasOffsetY);
+ GrCCAtlas* atlas = resources->renderPathInAtlas(draw.fLooseClippedIBounds, draw.fMatrix,
+ draw.fPath, &devBounds, &devBounds45,
+ &atlasOffsetX, &atlasOffsetY);
if (!atlas) {
SkDEBUGCODE(++fNumSkippedInstances);
continue;
diff --git a/src/gpu/ccpr/GrCCDrawPathsOp.h b/src/gpu/ccpr/GrCCDrawPathsOp.h
index 303f52b529..b46039d3c8 100644
--- a/src/gpu/ccpr/GrCCDrawPathsOp.h
+++ b/src/gpu/ccpr/GrCCDrawPathsOp.h
@@ -9,11 +9,11 @@
#define GrCCDrawPathsOp_DEFINED
#include "SkTInternalLList.h"
-#include "ccpr/GrCCPathParser.h"
#include "ccpr/GrCCPathProcessor.h"
#include "ccpr/GrCCSTLList.h"
#include "ops/GrDrawOp.h"
+struct GrCCPerFlushResourceSpecs;
class GrCCAtlas;
class GrCCPerFlushResources;
class GrCCPerOpListPaths;
@@ -26,13 +26,9 @@ public:
DEFINE_OP_CLASS_ID
SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrCCDrawPathsOp);
- static GrCCDrawPathsOp* Make(GrContext*,
- GrPaint&&,
- const SkIRect& clipIBounds,
- const SkMatrix&,
- const SkPath&,
- const SkRect& devBounds);
-
+ static std::unique_ptr<GrCCDrawPathsOp> Make(GrContext*, const SkIRect& clipIBounds,
+ const SkMatrix&, const SkPath&,
+ const SkRect& devBounds, GrPaint&&);
~GrCCDrawPathsOp() override;
const char* name() const override { return "GrCCDrawOp"; }
@@ -46,7 +42,7 @@ public:
void onPrepare(GrOpFlushState*) override {}
void wasRecorded(GrCCPerOpListPaths* owningPerOpListPaths);
- int countPaths(GrCCPathParser::PathStats*) const;
+ void accountForOwnPaths(GrCCPerFlushResourceSpecs*) const;
void setupResources(GrCCPerFlushResources*, GrOnFlushResourceProvider*);
SkDEBUGCODE(int numSkippedInstances_debugOnly() const { return fNumSkippedInstances; })
@@ -55,8 +51,8 @@ public:
private:
friend class GrOpMemoryPool;
- GrCCDrawPathsOp(GrPaint&&, const SkIRect& clipIBounds, const SkMatrix&, const SkPath&,
- const SkRect& devBounds);
+ GrCCDrawPathsOp(const SkIRect& clippedDevIBounds, const SkMatrix&, const SkPath&,
+ const SkRect& devBounds, GrPaint&&);
struct AtlasBatch {
const GrCCAtlas* fAtlas;
@@ -70,11 +66,11 @@ private:
fAtlasBatches.push_back() = {atlas, endInstanceIdx};
}
- const uint32_t fSRGBFlags;
const SkMatrix fViewMatrixIfUsingLocalCoords;
+ const uint32_t fSRGBFlags;
struct SingleDraw {
- SkIRect fClipIBounds;
+ SkIRect fLooseClippedIBounds;
SkMatrix fMatrix;
SkPath fPath;
GrColor fColor;
@@ -84,8 +80,8 @@ private:
GrCCSTLList<SingleDraw> fDraws;
SkDEBUGCODE(int fNumDraws = 1);
- GrProcessorSet fProcessors;
GrCCPerOpListPaths* fOwningPerOpListPaths = nullptr;
+ GrProcessorSet fProcessors;
int fBaseInstance;
SkSTArray<1, AtlasBatch, true> fAtlasBatches;
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index 3f02ac75f6..a80d789f3f 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -14,13 +14,14 @@
using PathInstance = GrCCPathProcessor::Instance;
GrCCPerFlushResources::GrCCPerFlushResources(GrOnFlushResourceProvider* onFlushRP,
- int numPathDraws, int numClipPaths,
- const GrCCPathParser::PathStats& pathStats)
- : fPathParser(sk_make_sp<GrCCPathParser>(numPathDraws + numClipPaths, pathStats))
+ const GrCCPerFlushResourceSpecs& specs)
+ : fPathParser(sk_make_sp<GrCCPathParser>(specs.fNumRenderedPaths + specs.fNumClipPaths,
+ specs.fParsingPathStats))
+ , fAtlasSpecs(specs.fAtlasSpecs)
, fIndexBuffer(GrCCPathProcessor::FindIndexBuffer(onFlushRP))
, fVertexBuffer(GrCCPathProcessor::FindVertexBuffer(onFlushRP))
, fInstanceBuffer(onFlushRP->makeBuffer(kVertex_GrBufferType,
- numPathDraws * sizeof(PathInstance))) {
+ specs.fNumRenderedPaths * sizeof(PathInstance))) {
if (!fIndexBuffer) {
SkDebugf("WARNING: failed to allocate CCPR index buffer. No paths will be drawn.\n");
return;
@@ -35,34 +36,31 @@ GrCCPerFlushResources::GrCCPerFlushResources(GrOnFlushResourceProvider* onFlushR
}
fPathInstanceData = static_cast<PathInstance*>(fInstanceBuffer->map());
SkASSERT(fPathInstanceData);
- SkDEBUGCODE(fPathInstanceBufferCount = numPathDraws);
+ SkDEBUGCODE(fPathInstanceBufferCount = specs.fNumRenderedPaths);
}
-GrCCAtlas* GrCCPerFlushResources::renderPathInAtlas(const GrCaps& caps, const SkIRect& clipIBounds,
- const SkMatrix& m, const SkPath& path,
- SkRect* devBounds, SkRect* devBounds45,
- int16_t* atlasOffsetX, int16_t* atlasOffsetY) {
+GrCCAtlas* GrCCPerFlushResources::renderPathInAtlas(const SkIRect& clipIBounds, const SkMatrix& m,
+ const SkPath& path, SkRect* devBounds,
+ SkRect* devBounds45, int16_t* atlasOffsetX,
+ int16_t* atlasOffsetY) {
SkASSERT(this->isMapped());
SkIRect devIBounds;
fPathParser->parsePath(m, path, devBounds, devBounds45);
devBounds->roundOut(&devIBounds);
- return this->placeParsedPathInAtlas(caps, clipIBounds, devIBounds, atlasOffsetX, atlasOffsetY);
+ return this->placeParsedPathInAtlas(clipIBounds, devIBounds, atlasOffsetX, atlasOffsetY);
}
-GrCCAtlas* GrCCPerFlushResources::renderDeviceSpacePathInAtlas(const GrCaps& caps,
- const SkIRect& clipIBounds,
+GrCCAtlas* GrCCPerFlushResources::renderDeviceSpacePathInAtlas(const SkIRect& clipIBounds,
const SkPath& devPath,
const SkIRect& devPathIBounds,
int16_t* atlasOffsetX,
int16_t* atlasOffsetY) {
SkASSERT(this->isMapped());
fPathParser->parseDeviceSpacePath(devPath);
- return this->placeParsedPathInAtlas(caps, clipIBounds, devPathIBounds, atlasOffsetX,
- atlasOffsetY);
+ return this->placeParsedPathInAtlas(clipIBounds, devPathIBounds, atlasOffsetX, atlasOffsetY);
}
-GrCCAtlas* GrCCPerFlushResources::placeParsedPathInAtlas(const GrCaps& caps,
- const SkIRect& clipIBounds,
+GrCCAtlas* GrCCPerFlushResources::placeParsedPathInAtlas(const SkIRect& clipIBounds,
const SkIRect& pathIBounds,
int16_t* atlasOffsetX,
int16_t* atlasOffsetY) {
@@ -87,7 +85,7 @@ GrCCAtlas* GrCCPerFlushResources::placeParsedPathInAtlas(const GrCaps& caps,
auto coverageCountBatchID = fPathParser->closeCurrentBatch();
fAtlases.back().setCoverageCountBatchID(coverageCountBatchID);
}
- fAtlases.emplace_back(caps, SkTMax(w, h));
+ fAtlases.emplace_back(fAtlasSpecs);
SkAssertResult(fAtlases.back().addRect(w, h, &atlasLocation));
}
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.h b/src/gpu/ccpr/GrCCPerFlushResources.h
index bc6b6edff3..14e3a1c667 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.h
+++ b/src/gpu/ccpr/GrCCPerFlushResources.h
@@ -15,23 +15,35 @@
#include "ccpr/GrCCPathProcessor.h"
/**
+ * This struct encapsulates the minimum and desired requirements for the GPU resources required by
+ * CCPR in a given flush.
+ */
+struct GrCCPerFlushResourceSpecs {
+ int fNumRenderedPaths = 0;
+ int fNumClipPaths = 0;
+ GrCCPathParser::PathStats fParsingPathStats;
+ GrCCAtlas::Specs fAtlasSpecs;
+
+ bool isEmpty() const { return 0 == fNumRenderedPaths + fNumClipPaths; }
+};
+
+/**
* This class wraps all the GPU resources that CCPR builds at flush time. It is allocated in CCPR's
* preFlush() method, and referenced by all the GrCCPerOpListPaths objects that are being flushed.
* It is deleted in postFlush() once all the flushing GrCCPerOpListPaths objects are deleted.
*/
class GrCCPerFlushResources : public GrNonAtomicRef<GrCCPerFlushResources> {
public:
- GrCCPerFlushResources(GrOnFlushResourceProvider*, int numPathDraws, int numClipPaths,
- const GrCCPathParser::PathStats&);
+ GrCCPerFlushResources(GrOnFlushResourceProvider*, const GrCCPerFlushResourceSpecs&);
bool isMapped() const { return SkToBool(fPathInstanceData); }
- GrCCAtlas* renderPathInAtlas(const GrCaps&, const SkIRect& clipIBounds, const SkMatrix&,
- const SkPath&, SkRect* devBounds, SkRect* devBounds45,
- int16_t* offsetX, int16_t* offsetY);
- GrCCAtlas* renderDeviceSpacePathInAtlas(const GrCaps&, const SkIRect& clipIBounds,
- const SkPath& devPath, const SkIRect& devPathIBounds,
- int16_t* atlasOffsetX, int16_t* atlasOffsetY);
+ GrCCAtlas* renderPathInAtlas(const SkIRect& clipIBounds, const SkMatrix&, const SkPath&,
+ SkRect* devBounds, SkRect* devBounds45, int16_t* offsetX,
+ int16_t* offsetY);
+ GrCCAtlas* renderDeviceSpacePathInAtlas(const SkIRect& clipIBounds, const SkPath& devPath,
+ const SkIRect& devPathIBounds, int16_t* atlasOffsetX,
+ int16_t* atlasOffsetY);
GrCCPathProcessor::Instance& appendDrawPathInstance() {
SkASSERT(this->isMapped());
@@ -47,11 +59,11 @@ public:
GrBuffer* instanceBuffer() const { SkASSERT(!this->isMapped()); return fInstanceBuffer.get(); }
private:
- GrCCAtlas* placeParsedPathInAtlas(const GrCaps&, const SkIRect& clipIBounds,
- const SkIRect& pathIBounds, int16_t* atlasOffsetX,
- int16_t* atlasOffsetY);
+ GrCCAtlas* placeParsedPathInAtlas(const SkIRect& clipIBounds, const SkIRect& pathIBounds,
+ int16_t* atlasOffsetX, int16_t* atlasOffsetY);
const sk_sp<GrCCPathParser> fPathParser;
+ const GrCCAtlas::Specs fAtlasSpecs;
sk_sp<const GrBuffer> fIndexBuffer;
sk_sp<const GrBuffer> fVertexBuffer;
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index dcb9a588aa..9ad945cad7 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -68,15 +68,6 @@ GrCCPerOpListPaths* GrCoverageCountingPathRenderer::lookupPendingPaths(uint32_t
return it->second.get();
}
-void GrCoverageCountingPathRenderer::adoptAndRecordOp(GrCCDrawPathsOp* op,
- const DrawPathArgs& args) {
- GrRenderTargetContext* rtc = args.fRenderTargetContext;
- if (uint32_t opListID = rtc->addDrawOp(*args.fClip, std::unique_ptr<GrDrawOp>(op))) {
- // If the Op wasn't dropped or combined, give it a pointer to its owning GrCCPerOpListPaths.
- op->wasRecorded(this->lookupPendingPaths(opListID));
- }
-}
-
GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
const CanDrawPathArgs& args) const {
if (args.fShape->hasUnstyledKey() && !fDrawCachablePaths) {
@@ -127,23 +118,34 @@ bool GrCoverageCountingPathRenderer::onDrawPath(const DrawPathArgs& args) {
SkRect devBounds;
args.fViewMatrix->mapRect(&devBounds, path.getBounds());
- GrCCDrawPathsOp* op;
+ std::unique_ptr<GrCCDrawPathsOp> op;
if (SkTMax(devBounds.height(), devBounds.width()) > kPathCropThreshold) {
// The path is too large. Crop it or analytic AA can run out of fp32 precision.
SkPath croppedPath;
path.transform(*args.fViewMatrix, &croppedPath);
crop_path(croppedPath, clipIBounds, &croppedPath);
- op = GrCCDrawPathsOp::Make(args.fContext, std::move(args.fPaint), clipIBounds,
- SkMatrix::I(), croppedPath, croppedPath.getBounds());
+ // FIXME: This breaks local coords: http://skbug.com/8003
+ op = GrCCDrawPathsOp::Make(args.fContext, clipIBounds, SkMatrix::I(), croppedPath,
+ croppedPath.getBounds(), std::move(args.fPaint));
} else {
- op = GrCCDrawPathsOp::Make(args.fContext, std::move(args.fPaint), clipIBounds,
- *args.fViewMatrix, path, devBounds);
+ op = GrCCDrawPathsOp::Make(args.fContext, clipIBounds, *args.fViewMatrix, path, devBounds,
+ std::move(args.fPaint));
}
- this->adoptAndRecordOp(op, args);
+ this->recordOp(std::move(op), args);
return true;
}
+void GrCoverageCountingPathRenderer::recordOp(std::unique_ptr<GrCCDrawPathsOp> opHolder,
+ const DrawPathArgs& args) {
+ if (GrCCDrawPathsOp* op = opHolder.get()) {
+ GrRenderTargetContext* rtc = args.fRenderTargetContext;
+ if (uint32_t opListID = rtc->addDrawOp(*args.fClip, std::move(opHolder))) {
+ op->wasRecorded(this->lookupPendingPaths(opListID));
+ }
+ }
+}
+
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
GrProxyProvider* proxyProvider,
uint32_t opListID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
@@ -186,11 +188,13 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
return; // Nothing to draw.
}
+ GrCCPerFlushResourceSpecs resourceSpecs;
+ int maxPreferredRTSize = onFlushRP->caps()->maxPreferredRenderTargetSize();
+ resourceSpecs.fAtlasSpecs.fMaxPreferredTextureSize = maxPreferredRTSize;
+ resourceSpecs.fAtlasSpecs.fMinTextureSize = SkTMin(1024, maxPreferredRTSize);
+
// Move the per-opList paths that are about to be flushed from fPendingPaths to fFlushingPaths,
- // and count up the paths about to be flushed so we can preallocate buffers.
- int numPathDraws = 0;
- int numClipPaths = 0;
- GrCCPathParser::PathStats flushingPathStats;
+ // and count them up so we can preallocate buffers.
fFlushingPaths.reserve(numOpListIDs);
for (int i = 0; i < numOpListIDs; ++i) {
auto iter = fPendingPaths.find(opListIDs[i]);
@@ -202,20 +206,18 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
fPendingPaths.erase(iter);
for (const GrCCDrawPathsOp* op : fFlushingPaths.back()->fDrawOps) {
- numPathDraws += op->countPaths(&flushingPathStats);
+ op->accountForOwnPaths(&resourceSpecs);
}
for (const auto& clipsIter : fFlushingPaths.back()->fClipPaths) {
- flushingPathStats.statPath(clipsIter.second.deviceSpacePath());
+ clipsIter.second.accountForOwnPath(&resourceSpecs);
}
- numClipPaths += fFlushingPaths.back()->fClipPaths.size();
}
- if (0 == numPathDraws + numClipPaths) {
+ if (resourceSpecs.isEmpty()) {
return; // Nothing to draw.
}
- auto resources = sk_make_sp<GrCCPerFlushResources>(onFlushRP, numPathDraws, numClipPaths,
- flushingPathStats);
+ auto resources = sk_make_sp<GrCCPerFlushResources>(onFlushRP, resourceSpecs);
if (!resources->isMapped()) {
return; // Some allocation failed.
}
@@ -231,7 +233,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
clipsIter.second.renderPathInAtlas(resources.get(), onFlushRP);
}
}
- SkASSERT(resources->nextPathInstanceIdx() == numPathDraws - numSkippedPaths);
+ SkASSERT(resources->nextPathInstanceIdx() == resourceSpecs.fNumRenderedPaths - numSkippedPaths);
// Allocate the atlases and create instance buffers to draw them.
if (!resources->finalize(onFlushRP, atlasDraws)) {
diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.h b/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
index 4032bd51d5..63e52a972e 100644
--- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
+++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
@@ -75,7 +75,7 @@ private:
: fDrawCachablePaths(drawCachablePaths) {}
GrCCPerOpListPaths* lookupPendingPaths(uint32_t opListID);
- void adoptAndRecordOp(GrCCDrawPathsOp*, const DrawPathArgs&);
+ void recordOp(std::unique_ptr<GrCCDrawPathsOp>, const DrawPathArgs&);
// fPendingPaths holds the GrCCPerOpListPaths objects that have already been created, but not
// flushed, and those that are still being created. All GrCCPerOpListPaths objects will first