diff options
-rw-r--r-- | include/core/SkImage.h | 5 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 4 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 25 | ||||
-rw-r--r-- | tests/ImageTest.cpp | 27 |
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); |