Update SkSpecialImage to be able to create tight SkImages and SkSurfaces
This calved off of: https://codereview.chromium.org/1810693003/ (Switch SkTileImageFilter over to new onFilterImage interface) since the TileImageFilter needs a tight bitmap/texture/image to perform its draw.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1816223002
Review URL: https://codereview.chromium.org/1816223002
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index 426a44e..03223a2 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -35,9 +35,13 @@
// Delete this entry point ASAP (see skbug.com/4965)
virtual bool getBitmapDeprecated(SkBitmap* result) const = 0;
+ virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
+
virtual sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const = 0;
- virtual sk_sp<SkSpecialImage> onMakeSubset(const SkIRect& subset) const = 0;
+ virtual sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const = 0;
+
+ virtual SkSurface* onMakeTightSurface(const SkImageInfo& info) const = 0;
private:
typedef SkSpecialImage INHERITED;
@@ -100,10 +104,19 @@
return as_SIB(this)->onMakeSurface(info);
}
+sk_sp<SkSurface> SkSpecialImage::makeTightSurface(const SkImageInfo& info) const {
+ sk_sp<SkSurface> tmp(SkRef(as_SIB(this)->onMakeTightSurface(info)));
+ return tmp;
+}
+
sk_sp<SkSpecialImage> SkSpecialImage::makeSubset(const SkIRect& subset) const {
return as_SIB(this)->onMakeSubset(subset);
}
+sk_sp<SkImage> SkSpecialImage::makeTightSubset(const SkIRect& subset) const {
+ return as_SIB(this)->onMakeTightSubset(subset);
+}
+
#if SK_SUPPORT_GPU
#include "SkGr.h"
#include "SkGrPixelRef.h"
@@ -227,6 +240,20 @@
subsetImg);
}
+ sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
+ return fImage->makeSubset(subset);
+ }
+
+ SkSurface* onMakeTightSurface(const SkImageInfo& info) const override {
+#if SK_SUPPORT_GPU
+ GrTexture* texture = as_IB(fImage.get())->peekTexture();
+ if (texture) {
+ return SkSurface::NewRenderTarget(texture->getContext(), SkBudgeted::kYes, info, 0);
+ }
+#endif
+ return SkSurface::NewRaster(info, nullptr);
+ }
+
private:
sk_sp<SkImage> fImage;
@@ -332,6 +359,20 @@
subsetBM);
}
+ sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
+ SkBitmap subsetBM;
+
+ if (!fBitmap.extractSubset(&subsetBM, subset)) {
+ return nullptr;
+ }
+
+ return SkImage::MakeFromBitmap(subsetBM);
+ }
+
+ SkSurface* onMakeTightSurface(const SkImageInfo& info) const override {
+ return SkSurface::NewRaster(info);
+ }
+
private:
SkBitmap fBitmap;
@@ -363,6 +404,7 @@
#if SK_SUPPORT_GPU
///////////////////////////////////////////////////////////////////////////////
#include "GrTexture.h"
+#include "SkImage_Gpu.h"
class SkSpecialImage_Gpu : public SkSpecialImage_Base {
public:
@@ -445,6 +487,34 @@
fAlphaType);
}
+ sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
+ if (0 == subset.fLeft && 0 == subset.fTop &&
+ fTexture->width() == subset.width() &&
+ fTexture->height() == subset.height()) {
+ // The existing GrTexture is already tight so reuse it in the SkImage
+ return sk_make_sp<SkImage_Gpu>(fTexture->width(), fTexture->height(),
+ kNeedNewImageUniqueID,
+ fAlphaType, fTexture, SkBudgeted::kYes);
+ }
+
+ GrContext* ctx = fTexture->getContext();
+ GrSurfaceDesc desc = fTexture->desc();
+ desc.fWidth = subset.width();
+ desc.fHeight = subset.height();
+
+ GrTexture* subTx = ctx->textureProvider()->createTexture(desc, SkBudgeted::kYes);
+ if (!subTx) {
+ return nullptr;
+ }
+ ctx->copySurface(subTx, fTexture, subset, SkIPoint::Make(0, 0));
+ return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
+ fAlphaType, subTx, SkBudgeted::kYes);
+ }
+
+ SkSurface* onMakeTightSurface(const SkImageInfo& info) const override {
+ return SkSurface::NewRenderTarget(fTexture->getContext(), SkBudgeted::kYes, info);
+ }
+
private:
SkAutoTUnref<GrTexture> fTexture;
const SkAlphaType fAlphaType;