blob: 7979dff9bdfb21345b76319ca4fba1c3197bfe5f [file] [log] [blame]
mtklein748ca3b2015-01-15 10:56:12 -08001#include "DMSrcSink.h"
2#include "SamplePipeControllers.h"
3#include "SkCommonFlags.h"
4#include "SkDocument.h"
5#include "SkMultiPictureDraw.h"
6#include "SkOSFile.h"
mtklein441b10e2015-01-28 11:12:25 -08007#include "SkPictureData.h"
mtklein748ca3b2015-01-15 10:56:12 -08008#include "SkPictureRecorder.h"
9#include "SkRandom.h"
scroggoa1193e42015-01-21 12:09:53 -080010#include "SkStream.h"
mtklein748ca3b2015-01-15 10:56:12 -080011
12namespace DM {
13
mtklein748ca3b2015-01-15 10:56:12 -080014GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
15
16Error GMSrc::draw(SkCanvas* canvas) const {
17 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
18 canvas->concat(gm->getInitialTransform());
19 gm->draw(canvas);
20 return "";
21}
22
23SkISize GMSrc::size() const {
24 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
25 return gm->getISize();
26}
27
28Name GMSrc::name() const {
29 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
30 return gm->getName();
31}
32
33/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
34
mtklein748ca3b2015-01-15 10:56:12 -080035ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {}
36
37Error ImageSrc::draw(SkCanvas* canvas) const {
mtklein75d98fd2015-01-18 07:05:01 -080038 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080039 if (!encoded) {
40 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
41 }
42 if (fSubsets == 0) {
43 // Decode the full image.
44 SkBitmap bitmap;
45 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap)) {
46 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
47 }
mtklein75d98fd2015-01-18 07:05:01 -080048 encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -080049 canvas->drawBitmap(bitmap, 0,0);
50 return "";
51 }
52 // Decode random subsets. This is a little involved.
scroggoa1193e42015-01-21 12:09:53 -080053 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
54 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
mtklein748ca3b2015-01-15 10:56:12 -080055 if (!decoder) {
56 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
57 }
scroggoa1193e42015-01-21 12:09:53 -080058 stream->rewind();
mtklein748ca3b2015-01-15 10:56:12 -080059 int w,h;
scroggoa1193e42015-01-21 12:09:53 -080060 if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
mtklein748ca3b2015-01-15 10:56:12 -080061 return ""; // Not an error. Subset decoding is not always supported.
62 }
63 SkRandom rand;
64 for (int i = 0; i < fSubsets; i++) {
65 SkIRect rect;
66 do {
67 rect.fLeft = rand.nextULessThan(w);
68 rect.fTop = rand.nextULessThan(h);
69 rect.fRight = rand.nextULessThan(w);
70 rect.fBottom = rand.nextULessThan(h);
71 rect.sort();
72 } while (rect.isEmpty());
73 SkBitmap subset;
74 if (!decoder->decodeSubset(&subset, rect, kUnknown_SkColorType/*use best fit*/)) {
75 return SkStringPrintf("Could not decode subset %d.\n", i);
76 }
77 canvas->drawBitmap(subset, SkIntToScalar(rect.fLeft), SkIntToScalar(rect.fTop));
78 }
79 return "";
80}
81
82SkISize ImageSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -080083 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080084 SkBitmap bitmap;
85 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
86 encoded->size(),
87 &bitmap,
88 kUnknown_SkColorType,
89 SkImageDecoder::kDecodeBounds_Mode)) {
90 return SkISize::Make(0,0);
91 }
92 return bitmap.dimensions();
93}
94
mtklein9264a952015-01-20 10:11:53 -080095Name ImageSrc::name() const {
96 Name name = SkOSPath::Basename(fPath.c_str());
97 if (fSubsets > 0) {
98 name.appendf("-%d-subsets", fSubsets);
99 }
100 return name;
101}
mtklein748ca3b2015-01-15 10:56:12 -0800102
103/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
104
mtklein748ca3b2015-01-15 10:56:12 -0800105SKPSrc::SKPSrc(SkString path) : fPath(path) {}
106
107Error SKPSrc::draw(SkCanvas* canvas) const {
scroggoa1193e42015-01-21 12:09:53 -0800108 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
mtklein75d98fd2015-01-18 07:05:01 -0800109 if (!stream) {
mtklein748ca3b2015-01-15 10:56:12 -0800110 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
111 }
mtklein75d98fd2015-01-18 07:05:01 -0800112 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
113 if (!pic) {
114 return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
115 }
116 stream.reset((SkStream*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -0800117 canvas->drawPicture(pic);
118 return "";
119}
120
121SkISize SKPSrc::size() const {
mtklein441b10e2015-01-28 11:12:25 -0800122 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
123 SkPictInfo info;
124 if (!stream || !SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
125 return SkISize::Make(0,0);
126 }
127 return info.fCullRect.roundOut().size();
mtklein748ca3b2015-01-15 10:56:12 -0800128}
129
130Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
131
132/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
133
mtklein441b10e2015-01-28 11:12:25 -0800134static SkISize limit_raster_dimensions(const SkISize& size) {
135 // This fits within a typical maximum texture, and puts a reasonable 16MB cap on raster bitmaps.
136 return SkISize::Make(SkTMin(2048, size.width()), SkTMin(2048, size.height()));
137}
138
mtklein82d28432015-01-15 12:46:02 -0800139GPUSink::GPUSink(GrContextFactory::GLContextType ct,
140 GrGLStandard api,
141 int samples,
142 bool dfText,
143 bool threaded)
mtklein748ca3b2015-01-15 10:56:12 -0800144 : fContextType(ct)
145 , fGpuAPI(api)
146 , fSampleCount(samples)
mtklein82d28432015-01-15 12:46:02 -0800147 , fUseDFText(dfText)
148 , fThreaded(threaded) {}
mtklein748ca3b2015-01-15 10:56:12 -0800149
150int GPUSink::enclave() const {
mtklein55e88b22015-01-21 15:50:13 -0800151 return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
mtklein748ca3b2015-01-15 10:56:12 -0800152}
153
mtklein748ca3b2015-01-15 10:56:12 -0800154Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtklein55e88b22015-01-21 15:50:13 -0800155 GrContextFactory factory;
mtklein441b10e2015-01-28 11:12:25 -0800156 const SkISize size = limit_raster_dimensions(src.size());
mtklein748ca3b2015-01-15 10:56:12 -0800157 const SkImageInfo info =
158 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
159 SkAutoTUnref<SkSurface> surface(
mtklein55e88b22015-01-21 15:50:13 -0800160 NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
mtklein748ca3b2015-01-15 10:56:12 -0800161 if (!surface) {
162 return "Could not create a surface.";
163 }
164 SkCanvas* canvas = surface->getCanvas();
165 Error err = src.draw(canvas);
166 if (!err.isEmpty()) {
167 return err;
168 }
169 canvas->flush();
170 dst->allocPixels(info);
171 canvas->readPixels(dst, 0,0);
mtklein55e88b22015-01-21 15:50:13 -0800172 if (FLAGS_abandonGpuContext) {
173 factory.abandonContexts();
174 }
mtklein748ca3b2015-01-15 10:56:12 -0800175 return "";
176}
177
178/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
179
180PDFSink::PDFSink() {}
181
182Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
183 SkSize size;
184 size = src.size();
185 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
186 SkCanvas* canvas = doc->beginPage(size.width(), size.height());
187
188 Error err = src.draw(canvas);
189 if (!err.isEmpty()) {
190 return err;
191 }
192 canvas->flush();
193 doc->endPage();
194 doc->close();
195 return "";
196}
197
198/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
199
mtklein9c3f17d2015-01-28 11:35:18 -0800200SKPSink::SKPSink() {}
201
202Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
203 SkSize size;
204 size = src.size();
205 SkPictureRecorder recorder;
206 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
207 if (!err.isEmpty()) {
208 return err;
209 }
210 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
211 pic->serialize(dst);
212 return "";
213}
214
215/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
216
mtklein748ca3b2015-01-15 10:56:12 -0800217RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
218
219Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtklein441b10e2015-01-28 11:12:25 -0800220 const SkISize size = limit_raster_dimensions(src.size());
mtklein748ca3b2015-01-15 10:56:12 -0800221 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
222 SkAlphaType alphaType = kPremul_SkAlphaType;
223 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
224
225 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
226 dst->eraseColor(SK_ColorTRANSPARENT);
227 SkCanvas canvas(*dst);
228 return src.draw(&canvas);
229}
230
231/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
232
233ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
234
235Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
236 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
237 struct ProxySrc : public Src {
238 const Src& fSrc;
239 SkMatrix fMatrix;
240 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
241
242 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
243 canvas->concat(fMatrix);
244 return fSrc.draw(canvas);
245 }
246 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
247 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
248 } proxy(src, fMatrix);
249 return fSink->draw(proxy, bitmap, stream);
250}
251
252/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
253
mtklein7edca212015-01-21 13:18:51 -0800254ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
mtklein748ca3b2015-01-15 10:56:12 -0800255
256Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
mtklein7edca212015-01-21 13:18:51 -0800257 // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
mtklein748ca3b2015-01-15 10:56:12 -0800258 struct ProxySrc : public Src {
259 const Src& fSrc;
mtklein7edca212015-01-21 13:18:51 -0800260 ProxySrc(const Src& src) : fSrc(src) {}
mtklein748ca3b2015-01-15 10:56:12 -0800261
262 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
263 SkISize size = this->size();
mtklein748ca3b2015-01-15 10:56:12 -0800264 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
265 SkGPipeWriter pipe;
mtklein7edca212015-01-21 13:18:51 -0800266 const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
267 return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
mtklein748ca3b2015-01-15 10:56:12 -0800268 }
269 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
270 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
mtklein7edca212015-01-21 13:18:51 -0800271 } proxy(src);
mtklein748ca3b2015-01-15 10:56:12 -0800272 return fSink->draw(proxy, bitmap, stream);
273}
274
275/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
276
277ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
278
279Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
280 // Record our Src into a picture.
281 SkSize size;
282 size = src.size();
283 SkPictureRecorder recorder;
284 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
285 if (!err.isEmpty()) {
286 return err;
287 }
288 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
289
290 // Serialize it and then deserialize it.
291 SkDynamicMemoryWStream wStream;
292 pic->serialize(&wStream);
scroggoa1193e42015-01-21 12:09:53 -0800293 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
mtklein748ca3b2015-01-15 10:56:12 -0800294 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
295
296 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
297 struct ProxySrc : public Src {
298 const SkPicture* fPic;
299 const SkISize fSize;
300 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
301
302 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
303 canvas->drawPicture(fPic);
304 return "";
305 }
306 SkISize size() const SK_OVERRIDE { return fSize; }
307 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
308 } proxy(deserialized, src.size());
309 return fSink->draw(proxy, bitmap, stream);
310}
311
312/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
313
314ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
315 : fW(w)
316 , fH(h)
317 , fFactory(factory)
318 , fSink(sink) {}
319
320Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
321 // Record our Src into a picture.
322 SkSize size;
323 size = src.size();
324 SkPictureRecorder recorder;
325 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
326 if (!err.isEmpty()) {
327 return err;
328 }
329 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
330
331 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
332 struct ProxySrc : public Src {
333 const int fW, fH;
334 const SkPicture* fPic;
335 const SkISize fSize;
336 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
337 : fW(w), fH(h), fPic(pic), fSize(size) {}
338
339 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
340 const int xTiles = (fSize.width() + fW - 1) / fW,
341 yTiles = (fSize.height() + fH - 1) / fH;
342 SkMultiPictureDraw mpd(xTiles*yTiles);
343 SkTDArray<SkSurface*> surfaces;
344 surfaces.setReserve(xTiles*yTiles);
345
346 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
347 for (int j = 0; j < yTiles; j++) {
348 for (int i = 0; i < xTiles; i++) {
349 // This lets our ultimate Sink determine the best kind of surface.
350 // E.g., if it's a GpuSink, the surfaces and images are textures.
351 SkSurface* s = canvas->newSurface(info);
352 if (!s) {
353 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
354 }
355 surfaces.push(s);
356 SkCanvas* c = s->getCanvas();
357 c->translate(SkIntToScalar(-i * fW),
358 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
359 mpd.add(c, fPic);
360 }
361 }
362 mpd.draw();
363 for (int j = 0; j < yTiles; j++) {
364 for (int i = 0; i < xTiles; i++) {
365 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
366 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
367 }
368 }
369 surfaces.unrefAll();
370 return "";
371 }
372 SkISize size() const SK_OVERRIDE { return fSize; }
373 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
374 } proxy(fW, fH, pic, src.size());
375 return fSink->draw(proxy, bitmap, stream);
376}
377
378} // namespace DM