aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkImage.h5
-rw-r--r--src/image/SkImage.cpp4
-rw-r--r--src/image/SkImage_Gpu.cpp25
-rw-r--r--tests/ImageTest.cpp27
4 files changed, 61 insertions, 0 deletions
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index c9c5668460..c0f37c3302 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -330,6 +330,11 @@ public:
sk_sp<SkImage> makeTextureImage(GrContext*) const;
/**
+ * If the image is texture-backed this will make a raster copy of it (or nullptr if reading back
+ * the pixels fails). Otherwise, it returns the original image.
+ */
+ sk_sp<SkImage> makeNonTextureImage() const;
+ /**
* Apply a given image filter to this image, and return the filtered result.
*
* The subset represents the active portion of this image. The return value is similarly an
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 88cf779081..b7f4225633 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -431,6 +431,10 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext*) const {
return nullptr;
}
+sk_sp<SkImage> SkImage::makeNonTextureImage() const {
+ return sk_ref_sp(const_cast<SkImage*>(this));
+}
+
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 7ce6450058..21ef52e463 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -332,6 +332,31 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext *context) const {
return create_image_from_maker(&maker, at, this->uniqueID());
}
+sk_sp<SkImage> SkImage::makeNonTextureImage() const {
+ GrTexture* texture = as_IB(this)->peekTexture();
+ if (!texture) {
+ return sk_ref_sp(const_cast<SkImage*>(this));
+ }
+ SkColorType ct;
+ sk_sp<SkColorSpace> cs;
+ if (!GrPixelConfigToColorAndColorSpace(texture->config(), &ct, &cs)) {
+ return nullptr;
+ }
+ SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+ auto info = SkImageInfo::Make(this->width(), this->height(), ct, at, cs);
+ size_t rowBytes = info.minRowBytes();
+ size_t size = info.getSafeSize(rowBytes);
+ auto data = SkData::MakeUninitialized(size);
+ if (!data) {
+ return nullptr;
+ }
+ SkPixmap pm(info, data->writable_data(), rowBytes);
+ if (!this->readPixels(pm, 0, 0, kDisallow_CachingHint)) {
+ return nullptr;
+ }
+ return MakeRasterData(info, data, rowBytes);
+}
+
sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext* ctx, const SkPixmap& pixmap,
SkBudgeted budgeted) {
if (!ctx) {
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 4d43e46eb1..0f760a6c73 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -475,6 +475,33 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_newTextureImage, reporter, contextInf
}
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeNonTextureImage, reporter, contextInfo) {
+ GrContext* context = contextInfo.grContext();
+
+ std::function<sk_sp<SkImage>()> imageFactories[] = {
+ create_image,
+ create_codec_image,
+ create_data_image,
+ create_picture_image,
+ [context] { return create_gpu_image(context); },
+ };
+ for (auto factory : imageFactories) {
+ sk_sp<SkImage> image = factory();
+ if (!image->isTextureBacked()) {
+ REPORTER_ASSERT(reporter, image->makeNonTextureImage().get() == image.get());
+ if (!(image = image->makeTextureImage(context))) {
+ continue;
+ }
+ }
+ auto rasterImage = image->makeNonTextureImage();
+ if (!rasterImage) {
+ ERRORF(reporter, "makeNonTextureImage failed for texture-backed image.");
+ }
+ REPORTER_ASSERT(reporter, !rasterImage->isTextureBacked());
+ assert_equal(reporter, image.get(), nullptr, rasterImage.get());
+ }
+}
+
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SkImage_drawAbandonedGpuImage, reporter, contextInfo) {
auto context = contextInfo.grContext();
auto image = create_gpu_image(context);