Add SkImage factory method that forces image to be resolved to a texture.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1631053003 Review URL: https://codereview.chromium.org/1631053003
This commit is contained in:
parent
9cd016e9b6
commit
8e74f80ca1
84
gm/image.cpp
84
gm/image.cpp
@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include "gm.h"
|
||||
#include "SkData.h"
|
||||
#include "SkCanvas.h"
|
||||
@ -429,3 +430,86 @@ private:
|
||||
typedef skiagm::GM INHERITED;
|
||||
};
|
||||
DEF_GM( return new ScaleGeneratorGM; )
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContextFactory.h"
|
||||
#endif
|
||||
|
||||
DEF_SIMPLE_GM(new_texture_image, canvas, 225, 60) {
|
||||
GrContext* context = nullptr;
|
||||
#if SK_SUPPORT_GPU
|
||||
context = canvas->getGrContext();
|
||||
GrContextFactory factory;
|
||||
#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 const int kSize = 50;
|
||||
SkBitmap bmp;
|
||||
bmp.allocN32Pixels(kSize, kSize);
|
||||
SkCanvas bmpCanvas(bmp);
|
||||
render_image(&bmpCanvas);
|
||||
|
||||
std::function<SkImage*()> imageFactories[] = {
|
||||
// Create sw raster image.
|
||||
[bmp] {
|
||||
return SkImage::NewFromBitmap(bmp);
|
||||
},
|
||||
// Create encoded image.
|
||||
[bmp] {
|
||||
SkAutoTUnref<SkData> src(
|
||||
SkImageEncoder::EncodeData(bmp, SkImageEncoder::kPNG_Type, 100));
|
||||
return SkImage::NewFromEncoded(src);
|
||||
},
|
||||
// Create a picture image.
|
||||
[render_image] {
|
||||
SkPictureRecorder recorder;
|
||||
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kSize), SkIntToScalar(kSize));
|
||||
render_image(canvas);
|
||||
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
|
||||
return SkImage::NewFromPicture(picture, SkISize::Make(kSize, kSize), nullptr, nullptr);
|
||||
},
|
||||
// Create a texture image
|
||||
[context, render_image]() -> SkImage* {
|
||||
SkAutoTUnref<SkSurface> surface(
|
||||
SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted,
|
||||
SkImageInfo::MakeN32Premul(kSize, kSize)));
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
render_image(surface->getCanvas());
|
||||
return surface->newImageSnapshot();
|
||||
}
|
||||
};
|
||||
|
||||
static const SkScalar kPad = 5.f;
|
||||
canvas->translate(kPad, kPad);
|
||||
for (auto factory : imageFactories) {
|
||||
SkAutoTUnref<SkImage> image(factory());
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
if (context) {
|
||||
SkAutoTUnref<SkImage> texImage(image->newTextureImage(context));
|
||||
if (texImage) {
|
||||
canvas->drawImage(texImage, 0, 0);
|
||||
}
|
||||
}
|
||||
canvas->translate(image->width() + kPad, 0);
|
||||
}
|
||||
}
|
||||
|
@ -300,6 +300,13 @@ public:
|
||||
*/
|
||||
SkImage* newSubset(const SkIRect& subset) const;
|
||||
|
||||
/**
|
||||
* Ensures that an image is backed by a texture (when GrContext is non-null). If no
|
||||
* transformation is required, the returned image may be the same as this image. If the this
|
||||
* image is from a different GrContext, this will fail.
|
||||
*/
|
||||
SkImage* newTextureImage(GrContext*) const;
|
||||
|
||||
// Helper functions to convert to SkBitmap
|
||||
|
||||
enum LegacyBitmapMode {
|
||||
|
@ -339,4 +339,8 @@ SkImage* SkImage::NewFromTextureCopy(GrContext*, const GrBackendTextureDesc&, Sk
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkImage* SkImage::newTextureImage(GrContext*) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -282,6 +282,37 @@ SkImage* SkImage::NewFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace colorS
|
||||
kOpaque_SkAlphaType, dst, budgeted);
|
||||
}
|
||||
|
||||
static SkImage* create_image_from_maker(GrTextureMaker* maker, SkAlphaType at, uint32_t id) {
|
||||
SkAutoTUnref<GrTexture> texture(maker->refTextureForParams(GrTextureParams::ClampNoFilter()));
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
return new SkImage_Gpu(texture->width(), texture->height(), id, at, texture,
|
||||
SkSurface::kNo_Budgeted);
|
||||
}
|
||||
|
||||
SkImage* SkImage::newTextureImage(GrContext *context) const {
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
if (GrTexture* peek = as_IB(this)->peekTexture()) {
|
||||
return peek->getContext() == context ? SkRef(const_cast<SkImage*>(this)) : nullptr;
|
||||
}
|
||||
// No way to check whether a image is premul or not?
|
||||
SkAlphaType at = this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
|
||||
|
||||
if (SkImageCacherator* cacher = as_IB(this)->peekCacherator()) {
|
||||
GrImageTextureMaker maker(context, cacher, this, kDisallow_CachingHint);
|
||||
return create_image_from_maker(&maker, at, this->uniqueID());
|
||||
}
|
||||
SkBitmap bmp;
|
||||
if (!this->asLegacyBitmap(&bmp, kRO_LegacyBitmapMode)) {
|
||||
return nullptr;
|
||||
}
|
||||
GrBitmapTextureMaker maker(context, bmp);
|
||||
return create_image_from_maker(&maker, at, this->uniqueID());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrTexture* GrDeepCopyTexture(GrTexture* src, bool budgeted) {
|
||||
|
@ -5,6 +5,9 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include "DMGpuSupport.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkData.h"
|
||||
@ -21,12 +24,6 @@
|
||||
#include "SkUtils.h"
|
||||
#include "Test.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrContext.h"
|
||||
#include "gl/GrGLInterface.h"
|
||||
#include "gl/GrGLUtil.h"
|
||||
#endif
|
||||
|
||||
static void assert_equal(skiatest::Reporter* reporter, SkImage* a, const SkIRect* subsetA,
|
||||
SkImage* b) {
|
||||
const int widthA = subsetA ? subsetA->width() : a->width();
|
||||
@ -87,6 +84,15 @@ static SkImage* create_data_image() {
|
||||
SkAutoTUnref<SkData> data(create_image_data(&info));
|
||||
return SkImage::NewRasterData(info, data, info.minRowBytes());
|
||||
}
|
||||
#if SK_SUPPORT_GPU // not gpu-specific but currently only used in GPU tests
|
||||
static SkImage* create_picture_image() {
|
||||
SkPictureRecorder recorder;
|
||||
SkCanvas* canvas = recorder.beginRecording(10, 10);
|
||||
canvas->clear(SK_ColorCYAN);
|
||||
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
|
||||
return SkImage::NewFromPicture(picture, SkISize::Make(10, 10), nullptr, nullptr);
|
||||
};
|
||||
#endif
|
||||
// Want to ensure that our Release is called when the owning image is destroyed
|
||||
struct RasterDataHolder {
|
||||
RasterDataHolder() : fReleaseCount(0) {}
|
||||
@ -376,6 +382,64 @@ DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_Gpu2Cpu, reporter, context) {
|
||||
REPORTER_ASSERT(reporter, !SkBitmapCache::Find(uniqueID, &cachedBitmap));
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_NATIVE_CONTEXT(SkImage_newTextureImage, reporter, context, glContext) {
|
||||
GrContextFactory otherFactory;
|
||||
GrContextFactory::ContextInfo otherContextInfo =
|
||||
otherFactory.getContextInfo(GrContextFactory::kNative_GLContextType);
|
||||
glContext->makeCurrent();
|
||||
|
||||
std::function<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.
|
||||
[glContext, otherContextInfo] {
|
||||
otherContextInfo.fGLContext->makeCurrent();
|
||||
SkImage* otherContextImage = create_gpu_image(otherContextInfo.fGrContext);
|
||||
glContext->makeCurrent();
|
||||
return otherContextImage;
|
||||
}
|
||||
};
|
||||
|
||||
for (auto factory : imageFactories) {
|
||||
SkAutoTUnref<SkImage> image(factory());
|
||||
if (!image) {
|
||||
ERRORF(reporter, "Error creating image.");
|
||||
continue;
|
||||
}
|
||||
GrTexture* origTexture = as_IB(image)->peekTexture();
|
||||
|
||||
SkAutoTUnref<SkImage> texImage(image->newTextureImage(context));
|
||||
if (!texImage) {
|
||||
// We execpt to fail if image comes from a different GrContext.
|
||||
if (!origTexture || origTexture->getContext() == context) {
|
||||
ERRORF(reporter, "newTextureImage failed.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
GrTexture* copyTexture = as_IB(texImage)->peekTexture();
|
||||
if (!copyTexture) {
|
||||
ERRORF(reporter, "newTextureImage returned non-texture image.");
|
||||
continue;
|
||||
}
|
||||
if (origTexture) {
|
||||
if (origTexture != copyTexture) {
|
||||
ERRORF(reporter, "newTextureImage made unnecessary texture copy.");
|
||||
}
|
||||
}
|
||||
if (image->width() != texImage->width() || image->height() != texImage->height()) {
|
||||
ERRORF(reporter, "newTextureImage changed the image size.");
|
||||
}
|
||||
if (image->isOpaque() != texImage->isOpaque()) {
|
||||
ERRORF(reporter, "newTextureImage changed image opaqueness.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// https://bug.skia.org/4390
|
||||
|
Loading…
Reference in New Issue
Block a user