Index: src/core/SkPictureShader.cpp |
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp |
index 1f4d3cd948b5a00433c3b282779dab282bcf6dd4..81e8ab42eed69e18efdd551a3a22ebf56e30ea29 100644 |
--- a/src/core/SkPictureShader.cpp |
+++ b/src/core/SkPictureShader.cpp |
@@ -10,6 +10,7 @@ |
#include "SkBitmap.h" |
#include "SkBitmapProcShader.h" |
#include "SkCanvas.h" |
+#include "SkImageGenerator.h" |
#include "SkMatrixUtils.h" |
#include "SkPicture.h" |
#include "SkReadBuffer.h" |
@@ -84,26 +85,12 @@ struct BitmapShaderRec : public SkResourceCache::Rec { |
result->reset(SkRef(rec.fShader.get())); |
- SkBitmap tile; |
- if (rec.fShader.get()->isABitmap(&tile, nullptr, nullptr)) { |
- // FIXME: this doesn't protect the pixels from being discarded as soon as we unlock. |
- // Should be handled via a pixel ref generator instead |
- // (https://code.google.com/p/skia/issues/detail?id=3220). |
- SkAutoLockPixels alp(tile, true); |
- return tile.getPixels() != nullptr; |
- } |
- return false; |
+ // The bitmap shader is backed by an image generator, thus it can always re-generate its |
+ // pixels if discarded. |
+ return true; |
} |
}; |
-static bool cache_try_alloc_pixels(SkBitmap* bitmap) { |
- SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); |
- |
- return nullptr != allocator |
- ? allocator->allocPixelRef(bitmap, nullptr) |
- : bitmap->tryAllocPixels(); |
-} |
- |
} // namespace |
SkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMode tmy, |
@@ -115,10 +102,6 @@ SkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMod |
, fTmy(tmy) { |
} |
-SkPictureShader::~SkPictureShader() { |
- fPicture->unref(); |
-} |
- |
SkShader* SkPictureShader::Create(const SkPicture* picture, TileMode tmx, TileMode tmy, |
const SkMatrix* localMatrix, const SkRect* tile) { |
if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) { |
@@ -232,19 +215,14 @@ SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatri |
this->getLocalMatrix()); |
if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) { |
+ SkMatrix matrix; |
+ matrix.setRectToRect(fTile, SkRect::MakeIWH(tileSize.width(), tileSize.height()), |
+ SkMatrix::kFill_ScaleToFit); |
SkBitmap bm; |
- bm.setInfo(SkImageInfo::MakeN32Premul(tileSize)); |
- if (!cache_try_alloc_pixels(&bm)) { |
- return SkShader::CreateEmptyShader(); |
+ if (!SkInstallDiscardablePixelRef( |
+ SkImageGenerator::NewFromPicture(tileSize, fPicture, &matrix, nullptr), &bm)) { |
+ return nullptr; |
} |
- bm.eraseColor(SK_ColorTRANSPARENT); |
- |
- // Always disable LCD text, since we can't assume our image will be opaque. |
- SkCanvas canvas(bm, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); |
- |
- canvas.scale(tileScale.width(), tileScale.height()); |
- canvas.translate(-fTile.x(), -fTile.y()); |
- canvas.drawPicture(fPicture); |
SkMatrix shaderMatrix = this->getLocalMatrix(); |
shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); |
@@ -324,10 +302,10 @@ void SkPictureShader::toString(SkString* str) const { |
}; |
str->appendf("PictureShader: [%f:%f:%f:%f] ", |
- fPicture ? fPicture->cullRect().fLeft : 0, |
- fPicture ? fPicture->cullRect().fTop : 0, |
- fPicture ? fPicture->cullRect().fRight : 0, |
- fPicture ? fPicture->cullRect().fBottom : 0); |
+ fPicture->cullRect().fLeft, |
+ fPicture->cullRect().fTop, |
+ fPicture->cullRect().fRight, |
+ fPicture->cullRect().fBottom); |
str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]); |