aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ops
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-03-07 11:54:37 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-07 19:25:10 +0000
commitd2e9f767bbb1a7664e9ee83d0755d7e4327cb7b2 (patch)
tree48e23613d7bb6f3c57ec16bf447390a704be5598 /src/gpu/ops
parentc7fbda95404a9422d0dd762d35383d5a61e89440 (diff)
Revise Text & Small Path Atlas so instantiation failure is handled at flush time
This paves the way to having the AtlasTextOps not need the RestrictedAtlasManager at op creation time. Change-Id: I1028faba730d50d3d3349a4c0809465d036ed611 Reviewed-on: https://skia-review.googlesource.com/111807 Reviewed-by: Jim Van Verth <jvanverth@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/gpu/ops')
-rw-r--r--src/gpu/ops/GrAtlasTextOp.cpp17
-rw-r--r--src/gpu/ops/GrSmallPathRenderer.cpp168
-rw-r--r--src/gpu/ops/GrSmallPathRenderer.h105
3 files changed, 171 insertions, 119 deletions
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 9e144ed278..07e114196b 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -292,9 +292,14 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY,
args.fColor, target->deferredUploadTarget(), glyphCache, fullAtlasManager,
&autoGlyphCache);
- GrAtlasTextBlob::VertexRegenerator::Result result;
- do {
- result = regenerator.regenerate();
+ bool done = false;
+ while (!done) {
+ GrAtlasTextBlob::VertexRegenerator::Result result;
+ if (!regenerator.regenerate(&result)) {
+ break;
+ }
+ done = result.fFinished;
+
// Copy regenerated vertices from the blob to our vertex buffer.
size_t vertexBytes = result.fGlyphsRegenerated * kVerticesPerGlyph * vertexStride;
if (args.fClipRect.isEmpty()) {
@@ -325,12 +330,16 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
this->flush(target, &flushInfo);
}
currVertex += vertexBytes;
- } while (!result.fFinished);
+ }
}
this->flush(target, &flushInfo);
}
void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
+ if (!flushInfo->fGlyphsToFlush) {
+ return;
+ }
+
auto fullAtlasManager = target->fullAtlasManager();
SkASSERT(fRestrictedAtlasManager == fullAtlasManager);
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 1607069118..73f0da567e 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -43,6 +43,91 @@ static const SkScalar kMaxDim = 73;
static const SkScalar kMinSize = SK_ScalarHalf;
static const SkScalar kMaxSize = 2*kMaxMIP;
+class ShapeDataKey {
+public:
+ ShapeDataKey() {}
+ ShapeDataKey(const ShapeDataKey& that) { *this = that; }
+ ShapeDataKey(const GrShape& shape, uint32_t dim) { this->set(shape, dim); }
+ ShapeDataKey(const GrShape& shape, const SkMatrix& ctm) { this->set(shape, ctm); }
+
+ ShapeDataKey& operator=(const ShapeDataKey& that) {
+ fKey.reset(that.fKey.count());
+ memcpy(fKey.get(), that.fKey.get(), fKey.count() * sizeof(uint32_t));
+ return *this;
+ }
+
+ // for SDF paths
+ void set(const GrShape& shape, uint32_t dim) {
+ // Shapes' keys are for their pre-style geometry, but by now we shouldn't have any
+ // relevant styling information.
+ SkASSERT(shape.style().isSimpleFill());
+ SkASSERT(shape.hasUnstyledKey());
+ int shapeKeySize = shape.unstyledKeySize();
+ fKey.reset(1 + shapeKeySize);
+ fKey[0] = dim;
+ shape.writeUnstyledKey(&fKey[1]);
+ }
+
+ // for bitmap paths
+ void set(const GrShape& shape, const SkMatrix& ctm) {
+ // Shapes' keys are for their pre-style geometry, but by now we shouldn't have any
+ // relevant styling information.
+ SkASSERT(shape.style().isSimpleFill());
+ SkASSERT(shape.hasUnstyledKey());
+ // We require the upper left 2x2 of the matrix to match exactly for a cache hit.
+ SkScalar sx = ctm.get(SkMatrix::kMScaleX);
+ SkScalar sy = ctm.get(SkMatrix::kMScaleY);
+ SkScalar kx = ctm.get(SkMatrix::kMSkewX);
+ SkScalar ky = ctm.get(SkMatrix::kMSkewY);
+ SkScalar tx = ctm.get(SkMatrix::kMTransX);
+ SkScalar ty = ctm.get(SkMatrix::kMTransY);
+ // Allow 8 bits each in x and y of subpixel positioning.
+ SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
+ SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
+ int shapeKeySize = shape.unstyledKeySize();
+ fKey.reset(5 + shapeKeySize);
+ fKey[0] = SkFloat2Bits(sx);
+ fKey[1] = SkFloat2Bits(sy);
+ fKey[2] = SkFloat2Bits(kx);
+ fKey[3] = SkFloat2Bits(ky);
+ fKey[4] = fracX | (fracY >> 8);
+ shape.writeUnstyledKey(&fKey[5]);
+ }
+
+ bool operator==(const ShapeDataKey& that) const {
+ return fKey.count() == that.fKey.count() &&
+ 0 == memcmp(fKey.get(), that.fKey.get(), sizeof(uint32_t) * fKey.count());
+ }
+
+ int count32() const { return fKey.count(); }
+ const uint32_t* data() const { return fKey.get(); }
+
+private:
+ // The key is composed of the GrShape's key, and either the dimensions of the DF
+ // generated for the path (32x32 max, 64x64 max, 128x128 max) if an SDF image or
+ // the matrix for the path with only fractional translation.
+ SkAutoSTArray<24, uint32_t> fKey;
+};
+
+class ShapeData {
+public:
+ ShapeDataKey fKey;
+ GrDrawOpAtlas::AtlasID fID;
+ SkRect fBounds;
+ GrIRect16 fTextureCoords;
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeData);
+
+ static inline const ShapeDataKey& GetKey(const ShapeData& data) {
+ return data.fKey;
+ }
+
+ static inline uint32_t Hash(ShapeDataKey key) {
+ return SkOpts::hash(key.data(), sizeof(uint32_t) * key.count32());
+ }
+};
+
+
+
// Callback to clear out internal path cache when eviction occurs
void GrSmallPathRenderer::HandleEviction(GrDrawOpAtlas::AtlasID id, void* pr) {
GrSmallPathRenderer* dfpr = (GrSmallPathRenderer*)pr;
@@ -134,8 +219,7 @@ private:
public:
DEFINE_OP_CLASS_ID
- using ShapeData = GrSmallPathRenderer::ShapeData;
- using ShapeCache = SkTDynamicHash<ShapeData, ShapeData::Key>;
+ using ShapeCache = SkTDynamicHash<ShapeData, ShapeDataKey>;
using ShapeDataList = GrSmallPathRenderer::ShapeDataList;
static std::unique_ptr<GrDrawOp> Make(GrPaint&& paint, const GrShape& shape,
@@ -330,7 +414,7 @@ private:
SkScalar desiredDimension = SkTMin(mipSize, kMaxMIP);
// check to see if df path is cached
- ShapeData::Key key(args.fShape, SkScalarCeilToInt(desiredDimension));
+ ShapeDataKey key(args.fShape, SkScalarCeilToInt(desiredDimension));
shapeData = fShapeCache->find(key);
if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
// Remove the stale cache entry
@@ -355,7 +439,7 @@ private:
}
} else {
// check to see if bitmap path is cached
- ShapeData::Key key(args.fShape, args.fViewMatrix);
+ ShapeDataKey key(args.fShape, args.fViewMatrix);
shapeData = fShapeCache->find(key);
if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
// Remove the stale cache entry
@@ -394,10 +478,32 @@ private:
this->flush(target, &flushInfo);
}
+ bool addToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, GrDrawOpAtlas* atlas,
+ int width, int height, const void* image,
+ GrDrawOpAtlas::AtlasID* id, SkIPoint16* atlasLocation) const {
+ auto resourceProvider = target->resourceProvider();
+ auto uploadTarget = target->deferredUploadTarget();
+
+ GrDrawOpAtlas::ErrorCode code = atlas->addToAtlas(resourceProvider, id,
+ uploadTarget, width, height,
+ image, atlasLocation);
+ if (GrDrawOpAtlas::ErrorCode::kError == code) {
+ return false;
+ }
+
+ if (GrDrawOpAtlas::ErrorCode::kTryAgain == code) {
+ this->flush(target, flushInfo);
+
+ code = atlas->addToAtlas(resourceProvider, id, uploadTarget, width, height,
+ image, atlasLocation);
+ }
+
+ return GrDrawOpAtlas::ErrorCode::kSucceeded == code;
+ }
+
bool addDFPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape,
uint32_t dimension, SkScalar scale) const {
- auto resourceProvider = target->resourceProvider();
const SkRect& bounds = shape.bounds();
@@ -486,14 +592,10 @@ private:
// add to atlas
SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id;
- auto uploadTarget = target->deferredUploadTarget();
- if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
- dfStorage.get(), &atlasLocation)) {
- this->flush(target, flushInfo);
- if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
- dfStorage.get(), &atlasLocation)) {
- return false;
- }
+
+ if (!this->addToAtlas(target, flushInfo, atlas,
+ width, height, dfStorage.get(), &id, &atlasLocation)) {
+ return false;
}
// add to cache
@@ -530,8 +632,6 @@ private:
bool addBMPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape,
const SkMatrix& ctm) const {
- auto resourceProvider = target->resourceProvider();
-
const SkRect& bounds = shape.bounds();
if (bounds.isEmpty()) {
return false;
@@ -591,14 +691,10 @@ private:
// add to atlas
SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id;
- auto uploadTarget = target->deferredUploadTarget();
- if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
- dst.addr(), &atlasLocation)) {
- this->flush(target, flushInfo);
- if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
- dst.addr(), &atlasLocation)) {
- return false;
- }
+
+ if (!this->addToAtlas(target, flushInfo, atlas,
+ dst.width(), dst.height(), dst.addr(), &id, &atlasLocation)) {
+ return false;
}
// add to cache
@@ -853,6 +949,21 @@ struct GrSmallPathRenderer::PathTestStruct {
ShapeDataList fShapeList;
};
+std::unique_ptr<GrDrawOp> GrSmallPathRenderer::createOp_TestingOnly(
+ GrPaint&& paint,
+ const GrShape& shape,
+ const SkMatrix& viewMatrix,
+ GrDrawOpAtlas* atlas,
+ ShapeCache* shapeCache,
+ ShapeDataList* shapeList,
+ bool gammaCorrect,
+ const GrUserStencilSettings* stencil) {
+
+ return GrSmallPathRenderer::SmallPathOp::Make(std::move(paint), shape, viewMatrix, atlas,
+ shapeCache, shapeList, gammaCorrect, stencil);
+
+}
+
GR_DRAW_OP_TEST_DEFINE(SmallPathOp) {
using PathTestStruct = GrSmallPathRenderer::PathTestStruct;
static PathTestStruct gTestStruct;
@@ -874,10 +985,13 @@ GR_DRAW_OP_TEST_DEFINE(SmallPathOp) {
// This path renderer only allows fill styles.
GrShape shape(GrTest::TestPath(random), GrStyle::SimpleFill());
-
- return GrSmallPathRenderer::SmallPathOp::Make(
- std::move(paint), shape, viewMatrix, gTestStruct.fAtlas.get(), &gTestStruct.fShapeCache,
- &gTestStruct.fShapeList, gammaCorrect, GrGetRandomStencil(random, context));
+ return GrSmallPathRenderer::createOp_TestingOnly(
+ std::move(paint), shape, viewMatrix,
+ gTestStruct.fAtlas.get(),
+ &gTestStruct.fShapeCache,
+ &gTestStruct.fShapeList,
+ gammaCorrect,
+ GrGetRandomStencil(random, context));
}
#endif
diff --git a/src/gpu/ops/GrSmallPathRenderer.h b/src/gpu/ops/GrSmallPathRenderer.h
index ef83c771a6..ab58bdf107 100644
--- a/src/gpu/ops/GrSmallPathRenderer.h
+++ b/src/gpu/ops/GrSmallPathRenderer.h
@@ -19,14 +19,14 @@
class GrContext;
+class ShapeData;
+class ShapeDataKey;
+
class GrSmallPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject {
public:
GrSmallPathRenderer();
~GrSmallPathRenderer() override;
- class SmallPathOp;
- struct PathTestStruct;
-
// GrOnFlushCallbackObject overrides
//
// Note: because this class is associated with a path renderer we want it to be removed from
@@ -41,13 +41,26 @@ public:
}
void postFlush(GrDeferredUploadToken startTokenForNextFlush,
- const uint32_t* opListIDs, int numOpListIDs) override {
+ const uint32_t* /*opListIDs*/, int /*numOpListIDs*/) override {
if (fAtlas) {
fAtlas->compact(startTokenForNextFlush);
}
}
+ using ShapeCache = SkTDynamicHash<ShapeData, ShapeDataKey>;
+ typedef SkTInternalLList<ShapeData> ShapeDataList;
+
+ static std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrPaint&&, const GrShape&,
+ const SkMatrix& viewMatrix,
+ GrDrawOpAtlas* atlas,
+ ShapeCache*, ShapeDataList*,
+ bool gammaCorrect,
+ const GrUserStencilSettings*);
+ struct PathTestStruct;
+
private:
+ class SmallPathOp;
+
StencilSupport onGetStencilSupport(const GrShape&) const override {
return GrPathRenderer::kNoSupport_StencilSupport;
}
@@ -56,92 +69,8 @@ private:
bool onDrawPath(const DrawPathArgs&) override;
- struct ShapeData {
- class Key {
- public:
- Key() {}
- Key(const Key& that) { *this = that; }
- Key(const GrShape& shape, uint32_t dim) { this->set(shape, dim); }
- Key(const GrShape& shape, const SkMatrix& ctm) { this->set(shape, ctm); }
-
- Key& operator=(const Key& that) {
- fKey.reset(that.fKey.count());
- memcpy(fKey.get(), that.fKey.get(), fKey.count() * sizeof(uint32_t));
- return *this;
- }
-
- // for SDF paths
- void set(const GrShape& shape, uint32_t dim) {
- // Shapes' keys are for their pre-style geometry, but by now we shouldn't have any
- // relevant styling information.
- SkASSERT(shape.style().isSimpleFill());
- SkASSERT(shape.hasUnstyledKey());
- int shapeKeySize = shape.unstyledKeySize();
- fKey.reset(1 + shapeKeySize);
- fKey[0] = dim;
- shape.writeUnstyledKey(&fKey[1]);
- }
-
- // for bitmap paths
- void set(const GrShape& shape, const SkMatrix& ctm) {
- // Shapes' keys are for their pre-style geometry, but by now we shouldn't have any
- // relevant styling information.
- SkASSERT(shape.style().isSimpleFill());
- SkASSERT(shape.hasUnstyledKey());
- // We require the upper left 2x2 of the matrix to match exactly for a cache hit.
- SkScalar sx = ctm.get(SkMatrix::kMScaleX);
- SkScalar sy = ctm.get(SkMatrix::kMScaleY);
- SkScalar kx = ctm.get(SkMatrix::kMSkewX);
- SkScalar ky = ctm.get(SkMatrix::kMSkewY);
- SkScalar tx = ctm.get(SkMatrix::kMTransX);
- SkScalar ty = ctm.get(SkMatrix::kMTransY);
- // Allow 8 bits each in x and y of subpixel positioning.
- SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
- SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
- int shapeKeySize = shape.unstyledKeySize();
- fKey.reset(5 + shapeKeySize);
- fKey[0] = SkFloat2Bits(sx);
- fKey[1] = SkFloat2Bits(sy);
- fKey[2] = SkFloat2Bits(kx);
- fKey[3] = SkFloat2Bits(ky);
- fKey[4] = fracX | (fracY >> 8);
- shape.writeUnstyledKey(&fKey[5]);
- }
-
- bool operator==(const Key& that) const {
- return fKey.count() == that.fKey.count() &&
- 0 == memcmp(fKey.get(), that.fKey.get(), sizeof(uint32_t) * fKey.count());
- }
-
- int count32() const { return fKey.count(); }
- const uint32_t* data() const { return fKey.get(); }
-
- private:
- // The key is composed of the GrShape's key, and either the dimensions of the DF
- // generated for the path (32x32 max, 64x64 max, 128x128 max) if an SDF image or
- // the matrix for the path with only fractional translation.
- SkAutoSTArray<24, uint32_t> fKey;
- };
- Key fKey;
- GrDrawOpAtlas::AtlasID fID;
- SkRect fBounds;
- GrIRect16 fTextureCoords;
- SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeData);
-
- static inline const Key& GetKey(const ShapeData& data) {
- return data.fKey;
- }
-
- static inline uint32_t Hash(Key key) {
- return SkOpts::hash(key.data(), sizeof(uint32_t) * key.count32());
- }
- };
-
static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
- typedef SkTDynamicHash<ShapeData, ShapeData::Key> ShapeCache;
- typedef SkTInternalLList<ShapeData> ShapeDataList;
-
std::unique_ptr<GrDrawOpAtlas> fAtlas;
ShapeCache fShapeCache;
ShapeDataList fShapeList;