aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm/image_pict.cpp
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-08-18 11:16:09 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-18 11:16:09 -0700
commit935d6cfaa78b6be75c9fcc596805f0f9b8da972e (patch)
tree2e3eb27f6c0a2d538f2e4e4922627a7c9e1fb30d /gm/image_pict.cpp
parentf272bb03df9b86e7ea2cf23fb4d5cc56624e0118 (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.cpp171
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