| Index: gm/image_pict.cpp
|
| diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
|
| index a8abea32b3cdecb654f89d129020586e5e65b7d4..010173974e33ee1358e291edab638716318e7275 100644
|
| --- a/gm/image_pict.cpp
|
| +++ b/gm/image_pict.cpp
|
| @@ -100,17 +100,102 @@ DEF_GM( return new ImagePictGM; )
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| +static SkImageGenerator* make_pic_generator(GrContext*, SkPicture* pic) {
|
| + SkMatrix matrix;
|
| + matrix.setTranslate(-100, -100);
|
| + return SkImageGenerator::NewFromPicture(SkISize::Make(100, 100), pic, &matrix, nullptr);
|
| +}
|
| +
|
| +class RasterGenerator : public SkImageGenerator {
|
| +public:
|
| + RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm) {}
|
| +protected:
|
| + bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
|
| + SkPMColor*, int*) override {
|
| + return fBM.readPixels(info, pixels, rowBytes, 0, 0);
|
| + }
|
| +private:
|
| + SkBitmap fBM;
|
| +};
|
| +static SkImageGenerator* make_ras_generator(GrContext*, SkPicture* pic) {
|
| + SkBitmap bm;
|
| + bm.allocN32Pixels(100, 100);
|
| + SkCanvas canvas(bm);
|
| + canvas.clear(0);
|
| + canvas.translate(-100, -100);
|
| + canvas.drawPicture(pic);
|
| + return new RasterGenerator(bm);
|
| +}
|
| +
|
| +class EmptyGenerator : public SkImageGenerator {
|
| +public:
|
| + EmptyGenerator(const SkImageInfo& info) : SkImageGenerator(info) {}
|
| +};
|
| +
|
| +#if SK_SUPPORT_GPU
|
| +class TextureGenerator : public SkImageGenerator {
|
| +public:
|
| + TextureGenerator(GrContext* ctx, const SkImageInfo& info, SkPicture* pic)
|
| + : SkImageGenerator(info)
|
| + , fCtx(SkRef(ctx))
|
| + {
|
| + SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted,
|
| + info, 0));
|
| + surface->getCanvas()->clear(0);
|
| + surface->getCanvas()->translate(-100, -100);
|
| + surface->getCanvas()->drawPicture(pic);
|
| + SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
|
| + fTexture.reset(SkRef(image->getTexture()));
|
| + }
|
| +protected:
|
| + GrTexture* onGenerateTexture(GrContext* ctx, SkImageUsageType, const SkIRect* subset) override {
|
| + if (ctx) {
|
| + SkASSERT(ctx == fCtx.get());
|
| + }
|
| +
|
| + if (!subset) {
|
| + return SkRef(fTexture.get());
|
| + }
|
| + // need to copy the subset into a new texture
|
| + GrSurfaceDesc desc = fTexture->desc();
|
| + desc.fWidth = subset->width();
|
| + desc.fHeight = subset->height();
|
| +
|
| + GrTexture* dst = fCtx->textureProvider()->createTexture(desc, false);
|
| + fCtx->copySurface(dst, fTexture, *subset, SkIPoint::Make(0, 0));
|
| + return dst;
|
| + }
|
| +private:
|
| + SkAutoTUnref<GrContext> fCtx;
|
| + SkAutoTUnref<GrTexture> fTexture;
|
| +};
|
| +static SkImageGenerator* make_tex_generator(GrContext* ctx, SkPicture* pic) {
|
| + const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
|
| +
|
| + if (!ctx) {
|
| + return new EmptyGenerator(info);
|
| + }
|
| + return new TextureGenerator(ctx, info, pic);
|
| +}
|
| +#endif
|
|
|
| class ImageCacheratorGM : public skiagm::GM {
|
| - SkAutoTUnref<SkPicture> fPicture;
|
| + SkString fName;
|
| + SkImageGenerator* (*fFactory)(GrContext*, SkPicture*);
|
| + SkAutoTUnref<SkPicture> fPicture;
|
| SkAutoTDelete<SkImageCacherator> fCache;
|
| + SkAutoTDelete<SkImageCacherator> fCacheSubset;
|
|
|
| public:
|
| - ImageCacheratorGM() {}
|
| + ImageCacheratorGM(const char suffix[], SkImageGenerator* (*factory)(GrContext*, SkPicture*))
|
| + : fFactory(factory)
|
| + {
|
| + fName.printf("image-cacherator-from-%s", suffix);
|
| + }
|
|
|
| protected:
|
| SkString onShortName() override {
|
| - return SkString("image-cacherator");
|
| + return fName;
|
| }
|
|
|
| SkISize onISize() override {
|
| @@ -122,42 +207,66 @@ protected:
|
| SkPictureRecorder recorder;
|
| draw_something(recorder.beginRecording(bounds), bounds);
|
| fPicture.reset(recorder.endRecording());
|
| + }
|
|
|
| - // extract enough just for the oval.
|
| - const SkISize size = SkISize::Make(100, 100);
|
| -
|
| - SkMatrix matrix;
|
| - matrix.setTranslate(-100, -100);
|
| - auto gen = SkImageGenerator::NewFromPicture(size, fPicture, &matrix, nullptr);
|
| + void makeCaches(GrContext* ctx) {
|
| + auto gen = fFactory(ctx, fPicture);
|
| + SkDEBUGCODE(const uint32_t genID = gen->uniqueID();)
|
| fCache.reset(SkImageCacherator::NewFromGenerator(gen));
|
| +
|
| + const SkIRect subset = SkIRect::MakeLTRB(50, 50, 100, 100);
|
| +
|
| + gen = fFactory(ctx, fPicture);
|
| + SkDEBUGCODE(const uint32_t genSubsetID = gen->uniqueID();)
|
| + fCacheSubset.reset(SkImageCacherator::NewFromGenerator(gen, &subset));
|
| +
|
| + // whole caches should have the same ID as the generator. Subsets should be diff
|
| + SkASSERT(fCache->uniqueID() == genID);
|
| + SkASSERT(fCacheSubset->uniqueID() != genID);
|
| + SkASSERT(fCacheSubset->uniqueID() != genSubsetID);
|
| +
|
| + SkASSERT(fCache->info().dimensions() == SkISize::Make(100, 100));
|
| + SkASSERT(fCacheSubset->info().dimensions() == SkISize::Make(50, 50));
|
| }
|
|
|
| - void drawSet(SkCanvas* canvas) const {
|
| - SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
|
| - canvas->drawPicture(fPicture, &matrix, nullptr);
|
| + static void draw_as_bitmap(SkCanvas* canvas, SkImageCacherator* cache, SkScalar x, SkScalar y) {
|
| + SkBitmap bitmap;
|
| + cache->lockAsBitmap(&bitmap);
|
| + canvas->drawBitmap(bitmap, x, y);
|
| + }
|
|
|
| - {
|
| - SkBitmap bitmap;
|
| - fCache->lockAsBitmap(&bitmap);
|
| - canvas->drawBitmap(bitmap, 150, 0);
|
| - }
|
| + static void draw_as_tex(SkCanvas* canvas, SkImageCacherator* cache, SkScalar x, SkScalar y) {
|
| #if SK_SUPPORT_GPU
|
| - {
|
| - SkAutoTUnref<GrTexture> texture(fCache->lockAsTexture(canvas->getGrContext(),
|
| - kUntiled_SkImageUsageType));
|
| - if (!texture) {
|
| - return;
|
| - }
|
| - // No API to draw a GrTexture directly, so we cheat and create a private image subclass
|
| - SkAutoTUnref<SkImage> image(new SkImage_Gpu(100, 100, fCache->generator()->uniqueID(),
|
| - kPremul_SkAlphaType, texture, 0,
|
| - SkSurface::kNo_Budgeted));
|
| - canvas->drawImage(image, 300, 0);
|
| + SkAutoTUnref<GrTexture> texture(cache->lockAsTexture(canvas->getGrContext(),
|
| + kUntiled_SkImageUsageType));
|
| + if (!texture) {
|
| + return;
|
| }
|
| + // No API to draw a GrTexture directly, so we cheat and create a private image subclass
|
| + SkAutoTUnref<SkImage> image(new SkImage_Gpu(cache->info().width(), cache->info().height(),
|
| + cache->uniqueID(), kPremul_SkAlphaType, texture,
|
| + 0, SkSurface::kNo_Budgeted));
|
| + canvas->drawImage(image, x, y);
|
| #endif
|
| }
|
|
|
| + void drawSet(SkCanvas* canvas) const {
|
| + SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
|
| + canvas->drawPicture(fPicture, &matrix, nullptr);
|
| +
|
| + // Draw the tex first, so it doesn't hit a lucky cache from the raster version. This
|
| + // way we also can force the generateTexture call.
|
| +
|
| + draw_as_tex(canvas, fCache, 310, 0);
|
| + draw_as_tex(canvas, fCacheSubset, 310+101, 0);
|
| +
|
| + draw_as_bitmap(canvas, fCache, 150, 0);
|
| + draw_as_bitmap(canvas, fCacheSubset, 150+101, 0);
|
| + }
|
| +
|
| void onDraw(SkCanvas* canvas) override {
|
| + this->makeCaches(canvas->getGrContext());
|
| +
|
| canvas->translate(20, 20);
|
|
|
| this->drawSet(canvas);
|
| @@ -178,7 +287,11 @@ protected:
|
| private:
|
| typedef skiagm::GM INHERITED;
|
| };
|
| -DEF_GM( return new ImageCacheratorGM; )
|
| +DEF_GM( return new ImageCacheratorGM("picture", make_pic_generator); )
|
| +DEF_GM( return new ImageCacheratorGM("raster", make_ras_generator); )
|
| +#if SK_SUPPORT_GPU
|
| + DEF_GM( return new ImageCacheratorGM("texture", make_tex_generator); )
|
| +#endif
|
|
|
|
|
|
|
|
|