Bring back SkImage::makeTextureImage
Ensures that an image is GPU backed on the passed-in GrContxt. The new
version requires a destination color space (intended usage of the image),
so we can make a proper decision about decoded format.
This reverts commit d263413a2a
.
BUG=skia:
Change-Id: Ibccddbafc301779559592045ed5a5fa9264e7432
Reviewed-on: https://skia-review.googlesource.com/8116
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
2bb94e8147
commit
041f7dfc57
81
gm/image.cpp
81
gm/image.cpp
@ -427,3 +427,84 @@ private:
|
||||
typedef skiagm::GM INHERITED;
|
||||
};
|
||||
DEF_GM( return new ScaleGeneratorGM; )
|
||||
|
||||
DEF_SIMPLE_GM(new_texture_image, canvas, 225, 60) {
|
||||
GrContext* context = nullptr;
|
||||
#if SK_SUPPORT_GPU
|
||||
context = canvas->getGrContext();
|
||||
#endif
|
||||
if (!context) {
|
||||
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
auto render_image = [](SkCanvas* canvas) {
|
||||
canvas->clear(SK_ColorBLUE);
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorRED);
|
||||
canvas->drawRect(SkRect::MakeXYWH(10.f,10.f,10.f,10.f), paint);
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
canvas->drawRect(SkRect::MakeXYWH(30.f,10.f,10.f,10.f), paint);
|
||||
paint.setColor(SK_ColorYELLOW);
|
||||
canvas->drawRect(SkRect::MakeXYWH(10.f,30.f,10.f,10.f), paint);
|
||||
paint.setColor(SK_ColorCYAN);
|
||||
canvas->drawRect(SkRect::MakeXYWH(30.f,30.f,10.f,10.f), paint);
|
||||
};
|
||||
|
||||
static constexpr int kSize = 50;
|
||||
SkBitmap bmp;
|
||||
bmp.allocPixels(SkImageInfo::MakeS32(kSize, kSize, kPremul_SkAlphaType));
|
||||
SkCanvas bmpCanvas(bmp);
|
||||
render_image(&bmpCanvas);
|
||||
|
||||
std::function<sk_sp<SkImage>()> imageFactories[] = {
|
||||
// Create sw raster image.
|
||||
[bmp] {
|
||||
return SkImage::MakeFromBitmap(bmp);
|
||||
},
|
||||
// Create encoded image.
|
||||
[bmp] {
|
||||
sk_sp<SkData> src(
|
||||
sk_tool_utils::EncodeImageToData(bmp, SkEncodedImageFormat::kPNG, 100));
|
||||
return SkImage::MakeFromEncoded(std::move(src));
|
||||
},
|
||||
// Create a picture image.
|
||||
[render_image] {
|
||||
SkPictureRecorder recorder;
|
||||
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kSize), SkIntToScalar(kSize));
|
||||
render_image(canvas);
|
||||
sk_sp<SkColorSpace> srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
|
||||
return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
|
||||
SkISize::Make(kSize, kSize), nullptr, nullptr,
|
||||
SkImage::BitDepth::kU8, srgbColorSpace);
|
||||
},
|
||||
// Create a texture image
|
||||
[context, render_image]() -> sk_sp<SkImage> {
|
||||
auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kYes,
|
||||
SkImageInfo::MakeS32(kSize, kSize,
|
||||
kPremul_SkAlphaType)));
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
render_image(surface->getCanvas());
|
||||
return surface->makeImageSnapshot();
|
||||
}
|
||||
};
|
||||
|
||||
constexpr SkScalar kPad = 5.f;
|
||||
canvas->translate(kPad, kPad);
|
||||
for (auto factory : imageFactories) {
|
||||
auto image(factory());
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
if (context) {
|
||||
sk_sp<SkImage> texImage(image->makeTextureImage(context,
|
||||
canvas->imageInfo().colorSpace()));
|
||||
if (texImage) {
|
||||
canvas->drawImage(texImage, 0, 0);
|
||||
}
|
||||
}
|
||||
canvas->translate(image->width() + kPad, 0);
|
||||
}
|
||||
}
|
||||
|
@ -322,6 +322,14 @@ public:
|
||||
*/
|
||||
sk_sp<SkImage> makeSubset(const SkIRect& subset) const;
|
||||
|
||||
/**
|
||||
* Ensures that an image is backed by a texture (when GrContext is non-null), suitable for use
|
||||
* with surfaces that have the supplied destination color space. If no transformation is
|
||||
* required, the returned image may be the same as this image. If this image is from a
|
||||
* different GrContext, this will fail.
|
||||
*/
|
||||
sk_sp<SkImage> makeTextureImage(GrContext*, SkColorSpace* dstColorSpace) 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.
|
||||
|
@ -370,6 +370,10 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, SkColorSpace* dstColorSpace) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage::makeNonTextureImage() const {
|
||||
return sk_ref_sp(const_cast<SkImage*>(this));
|
||||
}
|
||||
|
@ -350,6 +350,38 @@ sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace
|
||||
std::move(imageColorSpace));
|
||||
}
|
||||
|
||||
static sk_sp<SkImage> create_image_from_maker(GrTextureMaker* maker, SkAlphaType at, uint32_t id,
|
||||
SkColorSpace* dstColorSpace) {
|
||||
sk_sp<SkColorSpace> texColorSpace;
|
||||
sk_sp<GrTexture> texture(maker->refTextureForParams(GrSamplerParams::ClampNoFilter(),
|
||||
dstColorSpace, &texColorSpace, nullptr));
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), id, at, std::move(texture),
|
||||
std::move(texColorSpace), SkBudgeted::kNo);
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage::makeTextureImage(GrContext *context, SkColorSpace* dstColorSpace) const {
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
if (GrTexture* peek = as_IB(this)->peekTexture()) {
|
||||
return peek->getContext() == context ? sk_ref_sp(const_cast<SkImage*>(this)) : nullptr;
|
||||
}
|
||||
|
||||
if (SkImageCacherator* cacher = as_IB(this)->peekCacherator()) {
|
||||
GrImageTextureMaker maker(context, cacher, this, kDisallow_CachingHint);
|
||||
return create_image_from_maker(&maker, this->alphaType(), this->uniqueID(), dstColorSpace);
|
||||
}
|
||||
|
||||
if (const SkBitmap* bmp = as_IB(this)->onPeekBitmap()) {
|
||||
GrBitmapTextureMaker maker(context, *bmp);
|
||||
return create_image_from_maker(&maker, this->alphaType(), this->uniqueID(), dstColorSpace);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> SkImage::makeNonTextureImage() const {
|
||||
if (!this->isTextureBacked()) {
|
||||
return sk_ref_sp(const_cast<SkImage*>(this));
|
||||
|
@ -106,8 +106,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SpecialImage_GPUDevice, reporter, ctxInfo) {
|
||||
SkASSERT(SkIRect::MakeWH(kWidth, kHeight) == special->subset());
|
||||
|
||||
// Create a gpu-backed special image from a gpu-backed SkImage
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, bm.info()));
|
||||
image = surface->makeImageSnapshot();
|
||||
SkColorSpace* legacyColorSpace = nullptr;
|
||||
image = image->makeTextureImage(context, legacyColorSpace);
|
||||
special = DeviceTestingAccess::MakeSpecial(gpuDev.get(), image.get());
|
||||
SkASSERT(special->isTextureBacked());
|
||||
SkASSERT(kWidth == special->width());
|
||||
|
@ -457,6 +457,69 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(c, reporter, ctxInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage, reporter, contextInfo) {
|
||||
GrContext* context = contextInfo.grContext();
|
||||
sk_gpu_test::TestContext* testContext = contextInfo.testContext();
|
||||
|
||||
GrContextFactory otherFactory;
|
||||
GrContextFactory::ContextType otherContextType =
|
||||
GrContextFactory::NativeContextTypeForBackend(testContext->backend());
|
||||
ContextInfo otherContextInfo = otherFactory.getContextInfo(otherContextType);
|
||||
testContext->makeCurrent();
|
||||
|
||||
std::function<sk_sp<SkImage>()> imageFactories[] = {
|
||||
create_image,
|
||||
create_codec_image,
|
||||
create_data_image,
|
||||
// Create an image from a picture.
|
||||
create_picture_image,
|
||||
// Create a texture image.
|
||||
[context] { return create_gpu_image(context); },
|
||||
// Create a texture image in a another GrContext.
|
||||
[testContext, otherContextInfo] {
|
||||
otherContextInfo.testContext()->makeCurrent();
|
||||
sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
|
||||
testContext->makeCurrent();
|
||||
return otherContextImage;
|
||||
}
|
||||
};
|
||||
|
||||
SkColorSpace* legacyColorSpace = nullptr;
|
||||
for (auto factory : imageFactories) {
|
||||
sk_sp<SkImage> image(factory());
|
||||
if (!image) {
|
||||
ERRORF(reporter, "Error creating image.");
|
||||
continue;
|
||||
}
|
||||
GrTexture* origTexture = as_IB(image)->peekTexture();
|
||||
|
||||
sk_sp<SkImage> texImage(image->makeTextureImage(context, legacyColorSpace));
|
||||
if (!texImage) {
|
||||
// We execpt to fail if image comes from a different GrContext.
|
||||
if (!origTexture || origTexture->getContext() == context) {
|
||||
ERRORF(reporter, "makeTextureImage failed.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
GrTexture* copyTexture = as_IB(texImage)->peekTexture();
|
||||
if (!copyTexture) {
|
||||
ERRORF(reporter, "makeTextureImage returned non-texture image.");
|
||||
continue;
|
||||
}
|
||||
if (origTexture) {
|
||||
if (origTexture != copyTexture) {
|
||||
ERRORF(reporter, "makeTextureImage made unnecessary texture copy.");
|
||||
}
|
||||
}
|
||||
if (image->width() != texImage->width() || image->height() != texImage->height()) {
|
||||
ERRORF(reporter, "makeTextureImage changed the image size.");
|
||||
}
|
||||
if (image->alphaType() != texImage->alphaType()) {
|
||||
ERRORF(reporter, "makeTextureImage changed image alpha type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeNonTextureImage, reporter, contextInfo) {
|
||||
GrContext* context = contextInfo.grContext();
|
||||
|
||||
@ -467,11 +530,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeNonTextureImage, reporter, contex
|
||||
create_picture_image,
|
||||
[context] { return create_gpu_image(context); },
|
||||
};
|
||||
SkColorSpace* legacyColorSpace = nullptr;
|
||||
for (auto factory : imageFactories) {
|
||||
sk_sp<SkImage> image = factory();
|
||||
if (!image->isTextureBacked()) {
|
||||
REPORTER_ASSERT(reporter, image->makeNonTextureImage().get() == image.get());
|
||||
continue;
|
||||
if (!(image = image->makeTextureImage(context, legacyColorSpace))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto rasterImage = image->makeNonTextureImage();
|
||||
if (!rasterImage) {
|
||||
|
Loading…
Reference in New Issue
Block a user