OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkImage.h" | 10 #include "SkImage.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 canvas->restore(); | 93 canvas->restore(); |
94 } | 94 } |
95 | 95 |
96 private: | 96 private: |
97 typedef skiagm::GM INHERITED; | 97 typedef skiagm::GM INHERITED; |
98 }; | 98 }; |
99 DEF_GM( return new ImagePictGM; ) | 99 DEF_GM( return new ImagePictGM; ) |
100 | 100 |
101 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 101 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
102 | 102 |
| 103 static SkImageGenerator* make_pic_generator(GrContext*, SkPicture* pic) { |
| 104 SkMatrix matrix; |
| 105 matrix.setTranslate(-100, -100); |
| 106 return SkImageGenerator::NewFromPicture(SkISize::Make(100, 100), pic, &matri
x, nullptr); |
| 107 } |
| 108 |
| 109 class RasterGenerator : public SkImageGenerator { |
| 110 public: |
| 111 RasterGenerator(const SkBitmap& bm) : SkImageGenerator(bm.info()), fBM(bm) {
} |
| 112 protected: |
| 113 bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, |
| 114 SkPMColor*, int*) override { |
| 115 return fBM.readPixels(info, pixels, rowBytes, 0, 0); |
| 116 } |
| 117 private: |
| 118 SkBitmap fBM; |
| 119 }; |
| 120 static SkImageGenerator* make_ras_generator(GrContext*, SkPicture* pic) { |
| 121 SkBitmap bm; |
| 122 bm.allocN32Pixels(100, 100); |
| 123 SkCanvas canvas(bm); |
| 124 canvas.clear(0); |
| 125 canvas.translate(-100, -100); |
| 126 canvas.drawPicture(pic); |
| 127 return new RasterGenerator(bm); |
| 128 } |
| 129 |
| 130 class EmptyGenerator : public SkImageGenerator { |
| 131 public: |
| 132 EmptyGenerator(const SkImageInfo& info) : SkImageGenerator(info) {} |
| 133 }; |
| 134 |
| 135 #if SK_SUPPORT_GPU |
| 136 class TextureGenerator : public SkImageGenerator { |
| 137 public: |
| 138 TextureGenerator(GrContext* ctx, const SkImageInfo& info, SkPicture* pic) |
| 139 : SkImageGenerator(info) |
| 140 , fCtx(SkRef(ctx)) |
| 141 { |
| 142 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurfac
e::kNo_Budgeted, |
| 143 info, 0)); |
| 144 surface->getCanvas()->clear(0); |
| 145 surface->getCanvas()->translate(-100, -100); |
| 146 surface->getCanvas()->drawPicture(pic); |
| 147 SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); |
| 148 fTexture.reset(SkRef(image->getTexture())); |
| 149 } |
| 150 protected: |
| 151 GrTexture* onGenerateTexture(GrContext* ctx, SkImageUsageType, const SkIRect
* subset) override { |
| 152 if (ctx) { |
| 153 SkASSERT(ctx == fCtx.get()); |
| 154 } |
| 155 |
| 156 if (!subset) { |
| 157 return SkRef(fTexture.get()); |
| 158 } |
| 159 // need to copy the subset into a new texture |
| 160 GrSurfaceDesc desc = fTexture->desc(); |
| 161 desc.fWidth = subset->width(); |
| 162 desc.fHeight = subset->height(); |
| 163 |
| 164 GrTexture* dst = fCtx->textureProvider()->createTexture(desc, false); |
| 165 fCtx->copySurface(dst, fTexture, *subset, SkIPoint::Make(0, 0)); |
| 166 return dst; |
| 167 } |
| 168 private: |
| 169 SkAutoTUnref<GrContext> fCtx; |
| 170 SkAutoTUnref<GrTexture> fTexture; |
| 171 }; |
| 172 static SkImageGenerator* make_tex_generator(GrContext* ctx, SkPicture* pic) { |
| 173 const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100); |
| 174 |
| 175 if (!ctx) { |
| 176 return new EmptyGenerator(info); |
| 177 } |
| 178 return new TextureGenerator(ctx, info, pic); |
| 179 } |
| 180 #endif |
103 | 181 |
104 class ImageCacheratorGM : public skiagm::GM { | 182 class ImageCacheratorGM : public skiagm::GM { |
105 SkAutoTUnref<SkPicture> fPicture; | 183 SkString fName; |
| 184 SkImageGenerator* (*fFactory)(GrContext*, SkPicture*); |
| 185 SkAutoTUnref<SkPicture> fPicture; |
106 SkAutoTDelete<SkImageCacherator> fCache; | 186 SkAutoTDelete<SkImageCacherator> fCache; |
| 187 SkAutoTDelete<SkImageCacherator> fCacheSubset; |
107 | 188 |
108 public: | 189 public: |
109 ImageCacheratorGM() {} | 190 ImageCacheratorGM(const char suffix[], SkImageGenerator* (*factory)(GrContex
t*, SkPicture*)) |
| 191 : fFactory(factory) |
| 192 { |
| 193 fName.printf("image-cacherator-from-%s", suffix); |
| 194 } |
110 | 195 |
111 protected: | 196 protected: |
112 SkString onShortName() override { | 197 SkString onShortName() override { |
113 return SkString("image-cacherator"); | 198 return fName; |
114 } | 199 } |
115 | 200 |
116 SkISize onISize() override { | 201 SkISize onISize() override { |
117 return SkISize::Make(850, 450); | 202 return SkISize::Make(850, 450); |
118 } | 203 } |
119 | 204 |
120 void onOnceBeforeDraw() override { | 205 void onOnceBeforeDraw() override { |
121 const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100); | 206 const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100); |
122 SkPictureRecorder recorder; | 207 SkPictureRecorder recorder; |
123 draw_something(recorder.beginRecording(bounds), bounds); | 208 draw_something(recorder.beginRecording(bounds), bounds); |
124 fPicture.reset(recorder.endRecording()); | 209 fPicture.reset(recorder.endRecording()); |
| 210 } |
125 | 211 |
126 // extract enough just for the oval. | 212 void makeCaches(GrContext* ctx) { |
127 const SkISize size = SkISize::Make(100, 100); | 213 auto gen = fFactory(ctx, fPicture); |
| 214 SkDEBUGCODE(const uint32_t genID = gen->uniqueID();) |
| 215 fCache.reset(SkImageCacherator::NewFromGenerator(gen)); |
128 | 216 |
129 SkMatrix matrix; | 217 const SkIRect subset = SkIRect::MakeLTRB(50, 50, 100, 100); |
130 matrix.setTranslate(-100, -100); | 218 |
131 auto gen = SkImageGenerator::NewFromPicture(size, fPicture, &matrix, nul
lptr); | 219 gen = fFactory(ctx, fPicture); |
132 fCache.reset(SkImageCacherator::NewFromGenerator(gen)); | 220 SkDEBUGCODE(const uint32_t genSubsetID = gen->uniqueID();) |
| 221 fCacheSubset.reset(SkImageCacherator::NewFromGenerator(gen, &subset)); |
| 222 |
| 223 // whole caches should have the same ID as the generator. Subsets should
be diff |
| 224 SkASSERT(fCache->uniqueID() == genID); |
| 225 SkASSERT(fCacheSubset->uniqueID() != genID); |
| 226 SkASSERT(fCacheSubset->uniqueID() != genSubsetID); |
| 227 |
| 228 SkASSERT(fCache->info().dimensions() == SkISize::Make(100, 100)); |
| 229 SkASSERT(fCacheSubset->info().dimensions() == SkISize::Make(50, 50)); |
| 230 } |
| 231 |
| 232 static void draw_as_bitmap(SkCanvas* canvas, SkImageCacherator* cache, SkSca
lar x, SkScalar y) { |
| 233 SkBitmap bitmap; |
| 234 cache->lockAsBitmap(&bitmap); |
| 235 canvas->drawBitmap(bitmap, x, y); |
| 236 } |
| 237 |
| 238 static void draw_as_tex(SkCanvas* canvas, SkImageCacherator* cache, SkScalar
x, SkScalar y) { |
| 239 #if SK_SUPPORT_GPU |
| 240 SkAutoTUnref<GrTexture> texture(cache->lockAsTexture(canvas->getGrContex
t(), |
| 241 kUntiled_SkImageUsa
geType)); |
| 242 if (!texture) { |
| 243 return; |
| 244 } |
| 245 // No API to draw a GrTexture directly, so we cheat and create a private
image subclass |
| 246 SkAutoTUnref<SkImage> image(new SkImage_Gpu(cache->info().width(), cache
->info().height(), |
| 247 cache->uniqueID(), kPremul_S
kAlphaType, texture, |
| 248 0, SkSurface::kNo_Budgeted))
; |
| 249 canvas->drawImage(image, x, y); |
| 250 #endif |
133 } | 251 } |
134 | 252 |
135 void drawSet(SkCanvas* canvas) const { | 253 void drawSet(SkCanvas* canvas) const { |
136 SkMatrix matrix = SkMatrix::MakeTrans(-100, -100); | 254 SkMatrix matrix = SkMatrix::MakeTrans(-100, -100); |
137 canvas->drawPicture(fPicture, &matrix, nullptr); | 255 canvas->drawPicture(fPicture, &matrix, nullptr); |
138 | 256 |
139 { | 257 // Draw the tex first, so it doesn't hit a lucky cache from the raster v
ersion. This |
140 SkBitmap bitmap; | 258 // way we also can force the generateTexture call. |
141 fCache->lockAsBitmap(&bitmap); | 259 |
142 canvas->drawBitmap(bitmap, 150, 0); | 260 draw_as_tex(canvas, fCache, 310, 0); |
143 } | 261 draw_as_tex(canvas, fCacheSubset, 310+101, 0); |
144 #if SK_SUPPORT_GPU | 262 |
145 { | 263 draw_as_bitmap(canvas, fCache, 150, 0); |
146 SkAutoTUnref<GrTexture> texture(fCache->lockAsTexture(canvas->getGrC
ontext(), | 264 draw_as_bitmap(canvas, fCacheSubset, 150+101, 0); |
147 kUntiled_SkIm
ageUsageType)); | |
148 if (!texture) { | |
149 return; | |
150 } | |
151 // No API to draw a GrTexture directly, so we cheat and create a pri
vate image subclass | |
152 SkAutoTUnref<SkImage> image(new SkImage_Gpu(100, 100, fCache->genera
tor()->uniqueID(), | |
153 kPremul_SkAlphaType, tex
ture, 0, | |
154 SkSurface::kNo_Budgeted)
); | |
155 canvas->drawImage(image, 300, 0); | |
156 } | |
157 #endif | |
158 } | 265 } |
159 | 266 |
160 void onDraw(SkCanvas* canvas) override { | 267 void onDraw(SkCanvas* canvas) override { |
| 268 this->makeCaches(canvas->getGrContext()); |
| 269 |
161 canvas->translate(20, 20); | 270 canvas->translate(20, 20); |
162 | 271 |
163 this->drawSet(canvas); | 272 this->drawSet(canvas); |
164 | 273 |
165 canvas->save(); | 274 canvas->save(); |
166 canvas->translate(0, 130); | 275 canvas->translate(0, 130); |
167 canvas->scale(0.25f, 0.25f); | 276 canvas->scale(0.25f, 0.25f); |
168 this->drawSet(canvas); | 277 this->drawSet(canvas); |
169 canvas->restore(); | 278 canvas->restore(); |
170 | 279 |
171 canvas->save(); | 280 canvas->save(); |
172 canvas->translate(0, 200); | 281 canvas->translate(0, 200); |
173 canvas->scale(2, 2); | 282 canvas->scale(2, 2); |
174 this->drawSet(canvas); | 283 this->drawSet(canvas); |
175 canvas->restore(); | 284 canvas->restore(); |
176 } | 285 } |
177 | 286 |
178 private: | 287 private: |
179 typedef skiagm::GM INHERITED; | 288 typedef skiagm::GM INHERITED; |
180 }; | 289 }; |
181 DEF_GM( return new ImageCacheratorGM; ) | 290 DEF_GM( return new ImageCacheratorGM("picture", make_pic_generator); ) |
| 291 DEF_GM( return new ImageCacheratorGM("raster", make_ras_generator); ) |
| 292 #if SK_SUPPORT_GPU |
| 293 DEF_GM( return new ImageCacheratorGM("texture", make_tex_generator); ) |
| 294 #endif |
182 | 295 |
183 | 296 |
184 | 297 |
OLD | NEW |