diff options
author | reed <reed@google.com> | 2015-08-18 11:16:09 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-18 11:16:09 -0700 |
commit | 935d6cfaa78b6be75c9fcc596805f0f9b8da972e (patch) | |
tree | 2e3eb27f6c0a2d538f2e4e4922627a7c9e1fb30d /gm/image_pict.cpp | |
parent | f272bb03df9b86e7ea2cf23fb4d5cc56624e0118 (diff) |
Add subsets to SkImageGenerator and SkImageCacherator
... to support subsets in SkImage!
BUG=skia:
Review URL: https://codereview.chromium.org/1301633002
Diffstat (limited to 'gm/image_pict.cpp')
-rw-r--r-- | gm/image_pict.cpp | 171 |
1 files changed, 142 insertions, 29 deletions
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp index a8abea32b3..010173974e 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 |